static void CalcRangedTrace(NPCInst npc, out Vec3f start, out Vec3f end) { Vec3f projStartPos; using (var matrix = Gothic.Types.zMat4.Create()) { var weapon = npc.GetDrawnWeapon(); var node = (weapon == null || weapon.ItemType == ItemTypes.WepBow) ? oCNpc.NPCNodes.RightHand : oCNpc.NPCNodes.LeftHand; npc.BaseInst.gVob.GetTrafoModelNodeToWorld(node, matrix); projStartPos = (Vec3f)matrix.Position; } const zCWorld.zTraceRay traceType = zCWorld.zTraceRay.Ignore_Alpha | zCWorld.zTraceRay.Ignore_Projectiles | zCWorld.zTraceRay.Ignore_Vob_No_Collision | zCWorld.zTraceRay.Ignore_NPC; var camVob = GothicGlobals.Game.GetCameraVob(); start = (Vec3f)camVob.Position; Vec3f ray = 500000f * (Vec3f)camVob.Direction; end = start + ray; using (var zStart = start.CreateGVec()) using (var zRay = ray.CreateGVec()) { var gWorld = GothicGlobals.Game.GetWorld(); if (gWorld.TraceRayNearestHit(zStart, zRay, traceType)) { end = (Vec3f)gWorld.Raytrace_FoundIntersection; } start = projStartPos; ray = end - start; start.SetGVec(zStart); ray.SetGVec(zRay); if (gWorld.TraceRayNearestHit(zStart, zRay, traceType)) { end = (Vec3f)gWorld.Raytrace_FoundIntersection; } } }
static void RequestShootAuto(NPCInst hero) { Vec3f start; using (var matrix = Gothic.Types.zMat4.Create()) { var weapon = hero.GetDrawnWeapon(); var node = (weapon == null || weapon.ItemType == ItemTypes.WepBow) ? oCNpc.NPCNodes.RightHand : oCNpc.NPCNodes.LeftHand; hero.BaseInst.gVob.GetTrafoModelNodeToWorld(node, matrix); start = (Vec3f)matrix.Position; } const zCWorld.zTraceRay traceType = zCWorld.zTraceRay.Ignore_Alpha | zCWorld.zTraceRay.Ignore_Projectiles | zCWorld.zTraceRay.Ignore_Vob_No_Collision | zCWorld.zTraceRay.Ignore_NPC; NPCInst enemy = PlayerFocus.GetFocusNPC(); Vec3f dir = enemy == null ? (Vec3f)hero.BaseInst.gVob.Direction : (enemy.GetPosition() - start).Normalise(); Vec3f ray = 500000f * dir; Vec3f end; using (var zStart = start.CreateGVec()) using (var zRay = ray.CreateGVec()) { var gWorld = GothicGlobals.Game.GetWorld(); if (gWorld.TraceRayNearestHit(zStart, zRay, traceType)) { end = (Vec3f)gWorld.Raytrace_FoundIntersection; } else { end = start + ray; } } NPCInst.Requests.Shoot(hero, start, end); }
static void Update() { NPCInst hero = currentPlayer; if (hero == null) { Deactivate(); return; } float maxYaw = Angles.Deg2Rad(60); bool fightMode = hero.IsInFightMode; ItemInst wep = hero.GetDrawnWeapon(); float maxRange = (fightMode && wep != null && wep.IsWepRanged) ? 3000 : 400; Vec3f heroPos = hero.GetPosition(); Angles heroAng = hero.GetAngles(); float bestFit = 2.0f; BaseVobInst bestVob = null; if (hero?.World?.BaseWorld != null) { hero.World.BaseWorld.ForEachVob(v => { BaseVobInst vob = (BaseVobInst)v.ScriptObject; if (vob == hero) { return; } bool hasPriority = false; if (fightMode) { if (!(vob is NPCInst npc)) { return; } if (npc.IsDead) { return; } if (bestVob != null) { NPCInst bestNPC = (NPCInst)bestVob; if (npc.IsUnconscious) { if (!bestNPC.IsUnconscious) { return; // alive targets are more important } } else { if (bestNPC.IsUnconscious) { hasPriority = true; } } if (npc.TeamID == hero.TeamID) { if (bestNPC.TeamID != hero.TeamID) { return; } } else { if (bestNPC.TeamID == hero.TeamID) { hasPriority = true; } } } } Vec3f targetPos; using (zVec3 z = zVec3.Create()) { vob.BaseInst.gVob.BBox3D.GetCenter(z); targetPos = (Vec3f)z; } float distance = heroPos.GetDistance(targetPos); if (distance > maxRange) { return; } float yaw = Angles.GetYawFromAtVector(targetPos - heroPos); yaw = Math.Abs(Angles.Difference(yaw, heroAng.Yaw)); if (yaw > maxYaw) { return; // target is not in front of hero } if (!CanSee(heroPos, targetPos, vob)) { return; } float fit = distance / maxRange + yaw / maxYaw; if (hasPriority || fit < bestFit) { bestVob = vob; bestFit = fit; } }); SetFocus(bestVob); } }
void PlayerUpdate() { if (ArenaClient.DetectSchinken) { fwdTelHelper.Update(GameTime.Ticks); upTelHelper.Update(GameTime.Ticks); } NPCInst hero = ScriptClient.Client.Character; var gAI = hero.BaseInst.gAI; if (hero.IsDead || hero.IsUnconscious) { LookAround(hero); return; } zCAICamera.CurrentCam.BestAzimuth = 0; if (freeAim) { FreeAiming(hero); return; } DoTurning(hero); if (KeyBind.Action.IsPressed() && hero.IsInFightMode) { var enemy = PlayerFocus.GetFocusNPC(); if (enemy == null || !enemy.IsSpawned || enemy.IsDead) { PlayerFocus.SetLockedTarget(null); // updates for new target } PlayerFocus.SetLockedTarget(PlayerFocus.GetFocusNPC()); } else { PlayerFocus.SetLockedTarget(null); } NPCMovement state = NPCMovement.Stand; if (!KeyBind.Action.IsPressed() || hero.Movement != NPCMovement.Stand) { if (KeyBind.MoveForward.IsPressed()) // move forward { state = NPCMovement.Forward; } else if (KeyBind.MoveBack.IsPressed()) // move backward { var drawnWeapon = hero.GetDrawnWeapon(); if (hero.IsInFightMode && (drawnWeapon == null || drawnWeapon.IsWepMelee)) { if (dodgeLock.IsReady) // don't spam { if (IsWarmup()) { return; } NPCInst.Requests.Attack(hero, FightMoves.Dodge); } return; } else { state = NPCMovement.Backward; } } else if (KeyBind.MoveLeft.IsPressed()) // strafe left { state = NPCMovement.Left; } else if (KeyBind.MoveRight.IsPressed()) // strafe right { state = NPCMovement.Right; } else { state = NPCMovement.Stand; } } if (nextStrafeChange > GameTime.Ticks) { state = hero.Movement; } if (state == NPCMovement.Forward) { // FIXME: use only a better CheckEnoughSpaceMoveForward if (hero.Movement == NPCMovement.Stand && !gAI.CheckEnoughSpaceMoveForward(true)) { state = NPCMovement.Stand; } else { gAI.CalcForceModelHalt(); if ((gAI.Bitfield0 & zCAIPlayer.Flags.ForceModelHalt) != 0) { gAI.Bitfield0 &= ~zCAIPlayer.Flags.ForceModelHalt; state = NPCMovement.Stand; } } } else if (state == NPCMovement.Backward) { if (!gAI.CheckEnoughSpaceMoveBackward(true)) { state = NPCMovement.Stand; } } else if (state == NPCMovement.Left) { if (!gAI.CheckEnoughSpaceMoveLeft(true)) { state = NPCMovement.Stand; } } else if (state == NPCMovement.Right) { if (!gAI.CheckEnoughSpaceMoveRight(true)) { state = NPCMovement.Stand; } } if (state != NPCMovement.Stand && IsWarmup()) { state = NPCMovement.Stand; } if (state == NPCMovement.Left || state == NPCMovement.Right || (state == NPCMovement.Forward && hero.IsInFightMode)) { if (hero.Movement != state) { nextStrafeChange = GameTime.Ticks + StrafeInterval; } } else { nextStrafeChange = 0; } hero.SetMovement(state); }