public ChestBonusRoomObj() { this.m_chestList = new List<ChestObj>(); this.m_elf = new NpcObj("Elf_Character"); this.m_elf.Scale = new Vector2(2f, 2f); this.m_gate = new PhysicsObj("CastleEntranceGate_Sprite", null); this.m_gate.IsWeighted = false; this.m_gate.IsCollidable = true; this.m_gate.CollisionTypeTag = 1; this.m_gate.Layer = -1f; }
public override void Dispose() { if (!base.IsDisposed) { this.m_elf = null; this.m_gate = null; this.m_chestList.Clear(); this.m_chestList = null; base.Dispose(); } }
public CastleEntranceRoomObj() { this.m_castleGate = new PhysicsObj("CastleEntranceGate_Sprite", null); this.m_castleGate.IsWeighted = false; this.m_castleGate.IsCollidable = true; this.m_castleGate.CollisionTypeTag = 1; this.m_castleGate.Layer = -1f; this.m_castleGate.OutlineWidth = 2; base.GameObjList.Add(this.m_castleGate); this.m_teleporter = new TeleporterObj(); base.GameObjList.Add(this.m_teleporter); }
public static bool TestCollision(PhysicsObj a, PhysicsObj b, out Vector3 normal, out float penetration) { normal = Vector3.zero; penetration = 0; Vector3 diff = a.position - b.position; //diff.y = 0; normal = diff.normalized; if (diff.sqrMagnitude == 0) return false; float distance = diff.magnitude; penetration = b.HalfSize + a.HalfSize - distance; if (penetration > 0) return true; return false; }
public void SwitchToMeleeAttack() { if (IsDead) { return; } var weapon = GetEquippedMissileWeapon(); var ammo = GetEquippedAmmo(); if (weapon == null && ammo == null) { return; } var actionChain = new ActionChain(); EnqueueMotion_Force(actionChain, MotionStance.NonCombat, MotionCommand.Ready, (MotionCommand)CurrentMotionState.Stance); EnqueueMotion_Force(actionChain, MotionStance.HandCombat, MotionCommand.Ready, MotionCommand.NonCombat); actionChain.AddAction(this, () => { if (IsDead) { return; } // actually destroys the missile weapon + ammo here, // to ensure they can't be re-selected from inventory if (weapon != null) { TryUnwieldObjectWithBroadcasting(weapon.Guid, out _, out _); weapon.Destroy(); } if (ammo != null) { TryUnwieldObjectWithBroadcasting(ammo.Guid, out _, out _); ammo.Destroy(); } EquipInventoryItems(true); var innerChain = new ActionChain(); EnqueueMotion_Force(innerChain, MotionStance.NonCombat, MotionCommand.Ready, (MotionCommand)CurrentMotionState.Stance); innerChain.AddAction(this, () => { if (IsDead) { return; } //DoAttackStance(); // inlined DoAttackStance() / slightly modified -- do not rely on SetCombatMode() for stance swapping time in 1 action, // as it doesn't support that anymore var newStanceTime = SetCombatMode(CombatMode.Melee); NextMoveTime = NextAttackTime = Timers.RunningTime + newStanceTime; PrevAttackTime = NextMoveTime - (AiUseMagicDelay ?? 3.0f); PhysicsObj.StartTimer(); // end inline ResetAttack(); SwitchWeaponsPending = false; // this is an unfortunate hack to fix the following scenario: // since this function can be called at any point in time now, // including when LaunchMissile -> EnqueueMotion is in the middle of an action queue, // CurrentMotionState.Stance can get reset to the previous combat stance if that happens var newStance = CurrentMotionState.Stance; var swapChain = new ActionChain(); swapChain.AddDelaySeconds(2.0f); swapChain.AddAction(this, () => CurrentMotionState.Stance = newStance); swapChain.EnqueueChain(); }); innerChain.EnqueueChain(); }); actionChain.EnqueueChain(); }
public void add_static_object(PhysicsObj obj) { StaticObjects.Add(obj); }
public static void ParseRooms(string filePath, ContentManager contentManager = null, bool isDLCMap = false) { CultureInfo cultureInfo = (CultureInfo)CultureInfo.CurrentCulture.Clone(); cultureInfo.NumberFormat.CurrencyDecimalSeparator = "."; XmlReaderSettings xmlReaderSettings = new XmlReaderSettings(); xmlReaderSettings.IgnoreComments = true; xmlReaderSettings.IgnoreWhitespace = true; XmlReader xmlReader; if (contentManager == null) { xmlReader = XmlReader.Create(filePath, xmlReaderSettings); } else { xmlReader = XmlReader.Create(contentManager.RootDirectory + "\\Levels\\" + filePath + ".xml", xmlReaderSettings); } RoomObj roomObj = null; RoomObj roomObj2 = null; RoomObj roomObj3 = null; RoomObj roomObj4 = null; RoomObj roomObj5 = null; while (xmlReader.Read()) { if (xmlReader.NodeType == XmlNodeType.Element) { if (xmlReader.Name == "RoomObject") { roomObj = new RoomObj(); LevelParser.ParseGenericXML(xmlReader, roomObj); if (isDLCMap) { roomObj.IsDLCMap = true; } roomObj2 = (roomObj.Clone() as RoomObj); roomObj3 = (roomObj.Clone() as RoomObj); roomObj4 = (roomObj.Clone() as RoomObj); roomObj5 = (roomObj.Clone() as RoomObj); } if (xmlReader.Name == "GameObject") { xmlReader.MoveToAttribute("Type"); string value = xmlReader.Value; GameObj gameObj = null; string key; switch (key = value) { case "CollHullObj": gameObj = new TerrainObj(0, 0); break; case "DoorObj": gameObj = new DoorObj(roomObj, 0, 0, GameTypes.DoorType.OPEN); break; case "ChestObj": if (xmlReader.MoveToAttribute("Fairy")) { if (bool.Parse(xmlReader.Value)) { gameObj = new FairyChestObj(null); (gameObj as ChestObj).ChestType = 4; } else { gameObj = new ChestObj(null); } } else { gameObj = new ChestObj(null); } break; case "HazardObj": gameObj = new HazardObj(0, 0); break; case "BorderObj": gameObj = new BorderObj(); break; case "EnemyObj": xmlReader.MoveToAttribute("Procedural"); if (!bool.Parse(xmlReader.Value)) { xmlReader.MoveToAttribute("EnemyType"); byte enemyType = byte.Parse(xmlReader.Value, NumberStyles.Any, cultureInfo); xmlReader.MoveToAttribute("Difficulty"); GameTypes.EnemyDifficulty difficulty = (GameTypes.EnemyDifficulty)Enum.Parse(typeof(GameTypes.EnemyDifficulty), xmlReader.Value, true); gameObj = EnemyBuilder.BuildEnemy((int)enemyType, null, null, null, difficulty, false); if (xmlReader.MoveToAttribute("Flip") && bool.Parse(xmlReader.Value)) { gameObj.Flip = SpriteEffects.FlipHorizontally; } if (xmlReader.MoveToAttribute("InitialDelay")) { (gameObj as EnemyObj).InitialLogicDelay = float.Parse(xmlReader.Value, NumberStyles.Any, cultureInfo); } } else { xmlReader.MoveToAttribute("EnemyType"); string value2 = xmlReader.Value; gameObj = new EnemyTagObj(); (gameObj as EnemyTagObj).EnemyType = value2; } break; case "EnemyOrbObj": { xmlReader.MoveToAttribute("OrbType"); int orbType = int.Parse(xmlReader.Value, NumberStyles.Any, cultureInfo); bool flag = false; if (xmlReader.MoveToAttribute("IsWaypoint")) { flag = bool.Parse(xmlReader.Value); } if (flag) { gameObj = new WaypointObj(); (gameObj as WaypointObj).OrbType = orbType; } else { gameObj = new EnemyOrbObj(); (gameObj as EnemyOrbObj).OrbType = orbType; if (xmlReader.MoveToAttribute("ForceFlying")) { (gameObj as EnemyOrbObj).ForceFlying = bool.Parse(xmlReader.Value); } } break; } case "SpriteObj": xmlReader.MoveToAttribute("SpriteName"); if (xmlReader.Value == "LightSource_Sprite") { gameObj = new LightSourceObj(); } else { gameObj = new SpriteObj(xmlReader.Value); } break; case "PhysicsObj": { xmlReader.MoveToAttribute("SpriteName"); gameObj = new PhysicsObj(xmlReader.Value, null); PhysicsObj physicsObj = gameObj as PhysicsObj; physicsObj.CollisionTypeTag = 5; physicsObj.CollidesBottom = false; physicsObj.CollidesLeft = false; physicsObj.CollidesRight = false; break; } case "PhysicsObjContainer": { bool flag2 = false; if (xmlReader.MoveToAttribute("Breakable")) { flag2 = bool.Parse(xmlReader.Value); } xmlReader.MoveToAttribute("SpriteName"); if (flag2) { gameObj = new BreakableObj(xmlReader.Value); } else { gameObj = new PhysicsObjContainer(xmlReader.Value, null); } break; } case "ObjContainer": xmlReader.MoveToAttribute("SpriteName"); gameObj = new ObjContainer(xmlReader.Value); break; case "PlayerStartObj": gameObj = new PlayerStartObj(); break; } LevelParser.ParseGenericXML(xmlReader, gameObj); GameTypes.LevelType levelType = GameTypes.LevelType.NONE; if (xmlReader.MoveToAttribute("LevelType")) { levelType = (GameTypes.LevelType)int.Parse(xmlReader.Value, NumberStyles.Any, cultureInfo); } if (levelType == GameTypes.LevelType.CASTLE) { LevelParser.StoreObj(gameObj, roomObj2); LevelParser.StoreSwappedObj(gameObj, GameTypes.LevelType.DUNGEON, roomObj3); LevelParser.StoreSwappedObj(gameObj, GameTypes.LevelType.TOWER, roomObj5); LevelParser.StoreSwappedObj(gameObj, GameTypes.LevelType.GARDEN, roomObj4); SpriteObj spriteObj = gameObj as SpriteObj; if (spriteObj != null && spriteObj.SpriteName == "CastleAssetFrame_Sprite") { spriteObj.ChangeSprite("FramePicture" + CDGMath.RandomInt(1, 16) + "_Sprite"); } } else if (levelType == GameTypes.LevelType.DUNGEON) { LevelParser.StoreObj(gameObj, roomObj3); } else if (levelType == GameTypes.LevelType.TOWER) { LevelParser.StoreObj(gameObj, roomObj5); } else if (levelType == GameTypes.LevelType.GARDEN) { LevelParser.StoreObj(gameObj, roomObj4); } else { LevelParser.StoreObj(gameObj, roomObj2); LevelParser.StoreObj(gameObj, roomObj3); LevelParser.StoreObj(gameObj, roomObj5); LevelParser.StoreObj(gameObj, roomObj4); LevelParser.StoreObj(gameObj, roomObj); } if (LevelEV.RUN_TESTROOM && (levelType == LevelEV.TESTROOM_LEVELTYPE || levelType == GameTypes.LevelType.CASTLE)) { if (levelType == LevelEV.TESTROOM_LEVELTYPE) { LevelParser.StoreObj(gameObj, roomObj); } else if (levelType == GameTypes.LevelType.CASTLE) { LevelParser.StoreSwappedObj(gameObj, LevelEV.TESTROOM_LEVELTYPE, roomObj); } } if (gameObj is PlayerStartObj) { RoomObj expr_65E = roomObj; expr_65E.Name += "DEBUG_ROOM"; } } } else if (xmlReader.NodeType == XmlNodeType.EndElement && xmlReader.Name == "RoomObject") { if (roomObj.X < 10000f && roomObj.Name != "Boss" && roomObj.Name != "ChallengeBoss") { if (!roomObj.Name.Contains("DEBUG_ROOM")) { if (roomObj.AddToCastlePool) { LevelBuilder2.StoreRoom(roomObj2, GameTypes.LevelType.CASTLE); LevelBuilder2.StoreSpecialRoom(roomObj2, GameTypes.LevelType.CASTLE, false); } if (roomObj.AddToDungeonPool) { LevelBuilder2.StoreRoom(roomObj3, GameTypes.LevelType.DUNGEON); LevelBuilder2.StoreSpecialRoom(roomObj3, GameTypes.LevelType.DUNGEON, false); } if (roomObj.AddToGardenPool) { LevelBuilder2.StoreRoom(roomObj4, GameTypes.LevelType.GARDEN); LevelBuilder2.StoreSpecialRoom(roomObj4, GameTypes.LevelType.GARDEN, false); } if (roomObj.AddToTowerPool) { LevelBuilder2.StoreRoom(roomObj5, GameTypes.LevelType.TOWER); LevelBuilder2.StoreSpecialRoom(roomObj5, GameTypes.LevelType.TOWER, false); } } if (roomObj.Name.Contains("DEBUG_ROOM")) { roomObj.Name = roomObj.Name.Replace("DEBUG_ROOM", ""); if (LevelEV.TESTROOM_LEVELTYPE != GameTypes.LevelType.CASTLE) { LevelBuilder2.StoreSpecialRoom(roomObj, GameTypes.LevelType.CASTLE, true); } LevelBuilder2.StoreSpecialRoom(roomObj, LevelEV.TESTROOM_LEVELTYPE, true); } } if (roomObj.X < 10000f && (roomObj.Name == "Boss" || roomObj.Name == "ChallengeBoss")) { LevelBuilder2.StoreSpecialRoom(roomObj, GameTypes.LevelType.CASTLE, false); } } } }
public ShadowObj(PhysicsObj physObj, ObjCell cell) { PhysObj = physObj; Cell = cell; }
public void InitObject(PhysicsObj obj, ObjectInfoState objectState) { ObjectInfo.Init(obj, objectState); }
public static MoveToManager Create(PhysicsObj obj, WeenieObject wobj) { var moveToManager = new MoveToManager(obj, wobj); return(moveToManager); }
public void SetObject(PhysicsObj physObj) { }
public static StickyManager Create(PhysicsObj obj) { return(new StickyManager(obj)); }
public bool CreateParticleEmitter(PhysicsObj obj, int emitterInfoID, int partIdx, AFrame offset, int emitterID) { return(false); }
/// <summary> /// For monster and CombatPet FindNextTarget /// - for monsters, contains players and combat pets /// - for combat pets, contains monsters /// </summary> private bool AddVisibleTarget(PhysicsObj obj, bool clamp = true, bool foeType = false) { if (PhysicsObj.WeenieObj.IsCombatPet) { // only tracking monsters if (!obj.WeenieObj.IsMonster) { Console.WriteLine($"{PhysicsObj.Name}.ObjectMaint.AddVisibleTarget({obj.Name}): tried to add a non-monster"); return(false); } } else if (PhysicsObj.WeenieObj.IsFactionMob) { // only tracking players, combat pets, and monsters of differing faction if (!obj.IsPlayer && !obj.WeenieObj.IsCombatPet && (!obj.WeenieObj.IsMonster || PhysicsObj.WeenieObj.SameFaction(obj))) { Console.WriteLine($"{PhysicsObj.Name}.ObjectMaint.AddVisibleTarget({obj.Name}): tried to add a non-player / non-combat pet / non-opposing faction mob"); return(false); } } else { // handle special case: // we want to select faction mobs for monsters inverse targets, // but not add to the original monster if (obj.WeenieObj.IsFactionMob) { obj.ObjMaint.AddVisibleTarget(PhysicsObj); return(false); } // handle special case: // if obj has a FoeType of this creature, and this creature doesn't have a FoeType for obj, // we only want to perform the inverse if (obj.WeenieObj.FoeType != null && obj.WeenieObj.FoeType == PhysicsObj.WeenieObj.WorldObject?.CreatureType && (PhysicsObj.WeenieObj.FoeType == null || obj.WeenieObj.WorldObject != null && PhysicsObj.WeenieObj.FoeType != obj.WeenieObj.WorldObject.CreatureType)) { obj.ObjMaint.AddVisibleTarget(PhysicsObj); return(false); } // only tracking players and combat pets if (!obj.IsPlayer && !obj.WeenieObj.IsCombatPet && PhysicsObj.WeenieObj.FoeType == null) { Console.WriteLine($"{PhysicsObj.Name}.ObjectMaint.AddVisibleTarget({obj.Name}): tried to add a non-player / non-combat pet"); return(false); } } if (PhysicsObj.DatObject) { Console.WriteLine($"{PhysicsObj.Name}.ObjectMaint.AddVisibleTarget({obj.Name}): tried to add player for dat object"); return(false); } if (clamp && InitialClamp && obj.IsPlayer && !obj.ObjMaint.KnownObjects.ContainsKey(obj.ID)) { var distSq = PhysicsObj.Position.Distance2DSquared(obj.Position); if (distSq > InitialClamp_DistSq) { return(false); } } // TryAdd for existing keys still modifies collection? if (VisibleTargets.ContainsKey(obj.ID)) { return(false); } //Console.WriteLine($"{PhysicsObj.Name} ({PhysicsObj.ID:X8}).ObjectMaint.AddVisibleTarget({obj.Name})"); VisibleTargets.Add(obj.ID, obj); // maintain inverse for monsters / combat pets if (!obj.IsPlayer) { obj.ObjMaint.AddVisibleTarget(PhysicsObj); } return(true); }
public StickyManager(PhysicsObj obj) { Init(); SetPhysicsObject(obj); }
private bool RemoveRetaliateTarget(PhysicsObj obj) { return(RetaliateTargets.Remove(obj.ID)); }
private bool RemoveVisibleTarget(PhysicsObj obj) { //Console.WriteLine($"{PhysicsObj.Name} ({PhysicsObj.ID:X8}).ObjectMaint.RemoveVisibleTarget({obj.Name})"); return(VisibleTargets.Remove(obj.ID)); }
public ObjectMaint(PhysicsObj obj) { PhysicsObj = obj; }
public static void AddStaticAnimatingObject(PhysicsObj obj) { StaticAnimatingObjects.Add(obj); }
public void HandleActionEnterPkLite() { // ensure permanent npk if (PlayerKillerStatus != PlayerKillerStatus.NPK || MinimumTimeSincePk != null) { Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.OnlyNonPKsMayEnterPKLite)); return; } if (TooBusyToRecall) { Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YoureTooBusy)); return; } EnqueueBroadcast(new GameMessageSystemChat($"{Name} is looking for a fight!", ChatMessageType.Broadcast), LocalBroadcastRange); // perform pk lite entry motion / effect IsBusy = true; var prevStance = CurrentMotionState.Stance; var actionChain = new ActionChain(); var animTime = 0.0f; animTime += EnqueueMotion_Force(actionChain, MotionStance.NonCombat, MotionCommand.EnterPKLite); actionChain.AddAction(this, () => { if (PropertyManager.GetBool("allow_pkl_bump").Item) { // check for collisions PlayerKillerStatus = PlayerKillerStatus.PKLite; var colliding = PhysicsObj.ethereal_check_for_collisions(); if (colliding) { // try initial placement var result = PhysicsObj.SetPositionSimple(PhysicsObj.Position, true); if (result == SetPositionError.OK) { // handle landblock update? SyncLocation(); // force broadcast Sequences.GetNextSequence(SequenceType.ObjectForcePosition); SendUpdatePosition(); } } } UpdateProperty(this, PropertyInt.PlayerKillerStatus, (int)PlayerKillerStatus.PKLite, true); Session.Network.EnqueueSend(new GameEventWeenieError(Session, WeenieError.YouAreNowPKLite)); }); // return to previous stance, if applicable if (prevStance != MotionStance.NonCombat) { animTime += EnqueueMotion_Force(actionChain, prevStance, MotionCommand.Ready, MotionCommand.NonCombat); } actionChain.AddAction(this, () => IsBusy = false); actionChain.EnqueueChain(); }
public static void RemoveStaticAnimatingObject(PhysicsObj obj) { StaticAnimatingObjects.Remove(obj); }
public void HandleActionJump(JumpPack jump) { StartJump = new ACE.Entity.Position(Location); //Console.WriteLine($"JumpPack: Velocity: {jump.Velocity}, Extent: {jump.Extent}"); var strength = Strength.Current; var capacity = EncumbranceSystem.EncumbranceCapacity((int)strength, AugmentationIncreasedCarryingCapacity); var burden = EncumbranceSystem.GetBurden(capacity, EncumbranceVal ?? 0); // calculate stamina cost for this jump var extent = Math.Clamp(jump.Extent, 0.0f, 1.0f); var staminaCost = MovementSystem.JumpStaminaCost(extent, burden, PKTimerActive); //Console.WriteLine($"Strength: {strength}, Capacity: {capacity}, Encumbrance: {EncumbranceVal ?? 0}, Burden: {burden}, StaminaCost: {staminaCost}"); // ensure player has enough stamina to jump /*if (staminaCost > Stamina.Current) * { * // get adjusted power * extent = MovementSystem.GetJumpPower(Stamina.Current, burden, false); * * staminaCost = (int)Stamina.Current; * * // adjust jump velocity * var velocityZ = MovementSystem.GetJumpHeight(burden, GetCreatureSkill(Skill.Jump).Current, extent, 1.0f); * * jump.Velocity.Z = velocityZ; * }*/ LastJumpTime = DateTime.UtcNow; UpdateVitalDelta(Stamina, -staminaCost); //Console.WriteLine($"Jump velocity: {jump.Velocity}"); // TODO: have server verify / scale magnitude if (FastTick) { if (!PhysicsObj.IsMovingOrAnimating) { //PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime - Physics.PhysicsGlobals.MinQuantum; PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime; } // perform jump in physics engine PhysicsObj.TransientState &= ~(Physics.TransientStateFlags.Contact | Physics.TransientStateFlags.WaterContact); PhysicsObj.calc_acceleration(); PhysicsObj.set_on_walkable(false); PhysicsObj.set_local_velocity(jump.Velocity, false); if (CombatMode == CombatMode.Magic && MagicState.IsCasting) { FailCast(); } } else { PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime; // set jump velocity //var glob_velocity = Vector3.Transform(jump.Velocity, Location.Rotation); //PhysicsObj.set_velocity(glob_velocity, true); // perform jump in physics engine PhysicsObj.TransientState &= ~(Physics.TransientStateFlags.Contact | Physics.TransientStateFlags.WaterContact); PhysicsObj.calc_acceleration(); PhysicsObj.set_on_walkable(false); PhysicsObj.set_local_velocity(jump.Velocity, false); } // this shouldn't be needed, but without sending this update motion / simulated movement event beforehand, // running forward and then performing a charged jump does an uncharged shallow arc jump instead // this hack fixes that... var movementData = new MovementData(this); movementData.IsAutonomous = true; movementData.MovementType = MovementType.Invalid; movementData.Invalid = new MovementInvalid(movementData); EnqueueBroadcast(new GameMessageUpdateMotion(this, movementData)); // broadcast jump EnqueueBroadcast(new GameMessageVectorUpdate(this)); if (MagicState.IsCasting && RecordCast.Enabled) { RecordCast.OnJump(jump); } }
public void SetPhysicsObject(PhysicsObj obj) { PhysicsObj = obj; }
public void OnMoveToState_ClientMethod(MoveToState moveToState) { var rawState = moveToState.RawMotionState; var prevState = LastMoveToState?.RawMotionState ?? RawMotionState.None; var mvp = new Physics.Animation.MovementParameters(); mvp.HoldKeyToApply = rawState.CurrentHoldKey; if (!PhysicsObj.IsMovingOrAnimating) { PhysicsObj.UpdateTime = PhysicsTimer.CurrentTime; } // ForwardCommand if (rawState.ForwardCommand != MotionCommand.Invalid) { // press new key if (prevState.ForwardCommand == MotionCommand.Invalid) { PhysicsObj.DoMotion((uint)MotionCommand.Ready, mvp); PhysicsObj.DoMotion((uint)rawState.ForwardCommand, mvp); } // press alternate key else if (prevState.ForwardCommand != rawState.ForwardCommand) { PhysicsObj.DoMotion((uint)rawState.ForwardCommand, mvp); } } else if (prevState.ForwardCommand != MotionCommand.Invalid) { // release key PhysicsObj.StopMotion((uint)prevState.ForwardCommand, mvp, true); } // StrafeCommand if (rawState.SidestepCommand != MotionCommand.Invalid) { // press new key if (prevState.SidestepCommand == MotionCommand.Invalid) { PhysicsObj.DoMotion((uint)rawState.SidestepCommand, mvp); } // press alternate key else if (prevState.SidestepCommand != rawState.SidestepCommand) { PhysicsObj.DoMotion((uint)rawState.SidestepCommand, mvp); } } else if (prevState.SidestepCommand != MotionCommand.Invalid) { // release key PhysicsObj.StopMotion((uint)prevState.SidestepCommand, mvp, true); } // TurnCommand if (rawState.TurnCommand != MotionCommand.Invalid) { // press new key if (prevState.TurnCommand == MotionCommand.Invalid) { PhysicsObj.DoMotion((uint)rawState.TurnCommand, mvp); } // press alternate key else if (prevState.TurnCommand != rawState.TurnCommand) { PhysicsObj.DoMotion((uint)rawState.TurnCommand, mvp); } } else if (prevState.TurnCommand != MotionCommand.Invalid) { // release key PhysicsObj.StopMotion((uint)prevState.TurnCommand, mvp, true); } }
public bool Execute(PhysicsObj obj) { return(false); }
/// <summary> /// Used by physics engine to actually update a player position /// Automatically notifies clients of updated position /// </summary> /// <param name="newPosition">The new position being requested, before verification through physics engine</param> /// <returns>TRUE if object moves to a different landblock</returns> public bool UpdatePlayerPosition(ACE.Entity.Position newPosition, bool forceUpdate = false) { //Console.WriteLine($"{Name}.UpdatePlayerPhysics({newPosition}, {forceUpdate}, {Teleporting})"); bool verifyContact = false; // possible bug: while teleporting, client can still send AutoPos packets from old landblock if (Teleporting && !forceUpdate) { return(false); } // pre-validate movement if (!ValidateMovement(newPosition)) { log.Error($"{Name}.UpdatePlayerPosition() - movement pre-validation failed from {Location} to {newPosition}"); return(false); } try { if (!forceUpdate) // This is needed beacuse this function might be called recursively { stopwatch.Restart(); } var success = true; if (PhysicsObj != null) { var distSq = Location.SquaredDistanceTo(newPosition); if (distSq > PhysicsGlobals.EpsilonSq) { /*var p = new Physics.Common.Position(newPosition); * var dist = PhysicsObj.Position.Distance(p); * Console.WriteLine($"Dist: {dist}");*/ if (newPosition.Landblock == 0x18A && Location.Landblock != 0x18A) { log.Info($"{Name} is getting swanky"); } if (!Teleporting) { var blockDist = PhysicsObj.GetBlockDist(Location.Cell, newPosition.Cell); // verify movement if (distSq > MaxSpeedSq && blockDist > 1) { //Session.Network.EnqueueSend(new GameMessageSystemChat("Movement error", ChatMessageType.Broadcast)); log.Warn($"MOVEMENT SPEED: {Name} trying to move from {Location} to {newPosition}, speed: {Math.Sqrt(distSq)}"); return(false); } // verify z-pos if (blockDist == 0 && LastGroundPos != null && newPosition.PositionZ - LastGroundPos.PositionZ > 10 && DateTime.UtcNow - LastJumpTime > TimeSpan.FromSeconds(1) && GetCreatureSkill(Skill.Jump).Current < 1000) { verifyContact = true; } } var curCell = LScape.get_landcell(newPosition.Cell); if (curCell != null) { //if (PhysicsObj.CurCell == null || curCell.ID != PhysicsObj.CurCell.ID) //PhysicsObj.change_cell_server(curCell); PhysicsObj.set_request_pos(newPosition.Pos, newPosition.Rotation, curCell, Location.LandblockId.Raw); if (FastTick) { success = PhysicsObj.update_object_server_new(); } else { success = PhysicsObj.update_object_server(); } if (PhysicsObj.CurCell == null && curCell.ID >> 16 != 0x18A) { PhysicsObj.CurCell = curCell; } if (verifyContact && !PhysicsObj.TransientState.HasFlag(TransientStateFlags.OnWalkable)) { log.Warn($"z-pos hacking detected for {Name}, lastGroundPos: {LastGroundPos.ToLOCString()} - requestPos: {newPosition.ToLOCString()}"); Location = new ACE.Entity.Position(LastGroundPos); Sequences.GetNextSequence(SequenceType.ObjectForcePosition); SendUpdatePosition(); return(false); } CheckMonsters(); } } else { PhysicsObj.Position.Frame.Orientation = newPosition.Rotation; } } // double update path: landblock physics update -> updateplayerphysics() -> update_object_server() -> Teleport() -> updateplayerphysics() -> return to end of original branch if (Teleporting && !forceUpdate) { return(true); } if (!success) { return(false); } var landblockUpdate = Location.Cell >> 16 != newPosition.Cell >> 16; Location = newPosition; if (RecordCast.Enabled) { RecordCast.Log($"CurPos: {Location.ToLOCString()}"); } if (RequestedLocationBroadcast || DateTime.UtcNow - LastUpdatePosition >= MoveToState_UpdatePosition_Threshold) { SendUpdatePosition(); } else { Session.Network.EnqueueSend(new GameMessageUpdatePosition(this)); } if (!InUpdate) { LandblockManager.RelocateObjectForPhysics(this, true); } return(landblockUpdate); } finally { if (!forceUpdate) // This is needed beacuse this function might be called recursively { var elapsedSeconds = stopwatch.Elapsed.TotalSeconds; ServerPerformanceMonitor.AddToCumulativeEvent(ServerPerformanceMonitor.CumulativeEventHistoryType.Player_Tick_UpdateObjectPhysics, elapsedSeconds); if (elapsedSeconds >= 0.100) // Yea, that ain't good.... { log.Warn($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPosition() at loc: {Location}"); } else if (elapsedSeconds >= 0.010) { log.Debug($"[PERFORMANCE][PHYSICS] {Guid}:{Name} took {(elapsedSeconds * 1000):N1} ms to process UpdatePlayerPosition() at loc: {Location}"); } } } }
public void SetPlayer(PhysicsObj player) { Player = player; }
/// <summary> /// Sets the corpse to the final position /// </summary> public void SetFinalPosition() { if (AttackTarget == null) { return; } var playerDir = AttackTarget.Location.GetCurrentDir(); Location.Pos = AttackTarget.Location.Pos + playerDir * (AttackTarget.PhysicsObj.GetRadius() + PhysicsObj.GetRadius()); SendUpdatePosition(); }
public void get_land_scenes() { // ported from Scenery Scenery = new List <PhysicsObj>(); // get the landblock cell offsets var blockX = (ID >> 24) * 8; var blockY = (ID >> 16 & 0xFF) * 8; for (var i = 0; i < Terrain.Count; i++) { var terrain = Terrain[(int)i]; var terrainType = terrain >> 2 & 0x1F; // TerrainTypes table size = 32 (grass, desert, volcano, etc.) var sceneType = terrain >> 11; // SceneTypes table size = 89 total, 32 which can be indexed for each terrain type var sceneInfo = (int)DatManager.PortalDat.RegionDesc.TerrainInfo.TerrainTypes[terrainType].SceneTypes[sceneType]; var scenes = DatManager.PortalDat.RegionDesc.SceneInfo.SceneTypes[sceneInfo].Scenes; if (scenes.Count == 0) { continue; } var cellX = i / LandDefs.VertexDim; var cellY = i % LandDefs.VertexDim; var globalCellX = (uint)(cellX + blockX); var globalCellY = (uint)(cellY + blockY); var cellMat = globalCellY * (712977289 * globalCellX + 1813693831) - 1109124029 * globalCellX + 2139937281; var offset = cellMat * 2.3283064e-10; var scene_idx = (int)(scenes.Count * offset); if (scene_idx >= scenes.Count) { scene_idx = 0; } var sceneId = scenes[scene_idx]; var scene = DatManager.PortalDat.ReadFromDat <Scene>(sceneId); var cellXMat = -1109124029 * globalCellX; var cellYMat = 1813693831 * globalCellY; cellMat = 1360117743 * globalCellX * globalCellY + 1888038839; for (uint j = 0; j < scene.Objects.Count; j++) { var obj = scene.Objects[(int)j]; var noise = (uint)(cellXMat + cellYMat - cellMat * (23399 + j)) * 2.3283064e-10; if (noise < obj.Freq && obj.WeenieObj == 0) { var position = Displace(obj, globalCellX, globalCellY, j); // ensure within landblock range, and not near road var lx = cellX * LandDefs.CellLength + position.X; var ly = cellY * LandDefs.CellLength + position.Y; // TODO: ensure walkable slope if (lx < 0 || ly < 0 || lx >= LandDefs.BlockLength || ly >= LandDefs.BlockLength || OnRoad(obj, lx, ly)) { continue; } // load scenery var pos = new Position(ID); pos.Frame.Origin = new Vector3(lx, ly, 0); pos.Frame.Orientation = Quaternion.CreateFromYawPitchRoll(0, 0, RotateObj(obj, globalCellX, globalCellY, j)); var outside = LandDefs.AdjustToOutside(pos); var cell = get_landcell(pos.ObjCellID); //if (cell == null) continue; Polygon walkable = null; var terrainPoly = cell.find_terrain_poly(pos.Frame.Origin, ref walkable); walkable.Plane.set_height(ref pos.Frame.Origin); // todo: collision detection var physicsObj = PhysicsObj.makeObject(obj.ObjId, 0, false); //physicsObj.set_initial_frame(pos.Frame); physicsObj.add_obj_to_cell(cell, pos.Frame); Scenery.Add(physicsObj); } } } //Console.WriteLine("Landblock " + ID.ToString("X8") + " scenery count: " + Scenery.Count); }
/// <summary> /// Returns the destination position the monster is attempting to move to /// to perform a melee attack /// </summary> public Vector3 GetDestination() { var dir = Vector3.Normalize(Location.ToGlobal() - AttackTarget.Location.ToGlobal()); return(AttackTarget.Location.Pos + dir * (AttackTarget.PhysicsObj.GetRadius() + PhysicsObj.GetRadius())); }
public void hide_object(PhysicsObj obj) { update_all_voyeur(obj, DetectionType.LeftDetection); }
public override void Initialize() { this.m_gate = new PhysicsObj("CastleEntranceGate_Sprite", null); this.m_gate.IsWeighted = false; this.m_gate.IsCollidable = true; this.m_gate.CollisionTypeTag = 1; this.m_gate.Layer = -1f; this.m_gate.OutlineWidth = 2; base.GameObjList.Add(this.m_gate); Rectangle rectangle = default(Rectangle); Color[] array = new Color[] { Color.Red, Color.Blue, Color.Green, Color.Yellow, Color.Orange, Color.Purple, Color.Pink, Color.MediumTurquoise, Color.CornflowerBlue }; foreach (GameObj current in base.GameObjList) { if (current is WaypointObj) { this.m_elf.X = current.X; } if (current.Name == "Balloon") { this.m_balloonList.Add(current as ObjContainer); (current as ObjContainer).GetChildAt(1).TextureColor = array[CDGMath.RandomInt(0, array.Length - 1)]; } } foreach (TerrainObj current2 in base.TerrainObjList) { if (current2.Name == "Floor") { this.m_elf.Y = current2.Y - ((float)this.m_elf.Bounds.Bottom - this.m_elf.Y) - 2f; } if (current2.Name == "GatePosition") { rectangle = current2.Bounds; } } this.m_gate.X = (float)rectangle.X; this.m_gate.Y = (float)rectangle.Bottom; if (!base.IsReversed) { this.m_elf.Flip = SpriteEffects.FlipHorizontally; } base.GameObjList.Add(this.m_elf); foreach (TerrainObj current3 in base.TerrainObjList) { if (current3.Name == "Boundary") { current3.Visible = false; this.m_targetBounds = current3.Bounds; break; } } float num = 10f; float num2 = (float)(this.m_targetBounds.X + 40); float num3 = (float)this.m_targetBounds.Y; float num4 = (float)this.m_targetBounds.Width / num; float num5 = (float)this.m_targetBounds.Height / num; int num6 = 0; while ((float)num6 < num * num) { BreakableObj breakableObj = new BreakableObj("Target2_Character"); breakableObj.X = num2; breakableObj.Y = num3; breakableObj.Scale = new Vector2(1.6f, 1.6f); breakableObj.OutlineWidth = 2; breakableObj.HitBySpellsOnly = true; breakableObj.IsWeighted = false; this.m_targetList.Add(breakableObj); breakableObj.SameTypesCollide = false; breakableObj.DropItem = false; base.GameObjList.Add(breakableObj); num2 += num4; if ((float)(num6 + 1) % num == 0f) { num2 = (float)(this.m_targetBounds.X + 40); num3 += num5; } num6++; } this.m_rewardChest = new ChestObj(null); this.m_rewardChest.ChestType = 3; if (!base.IsReversed) { this.m_rewardChest.Flip = SpriteEffects.FlipHorizontally; this.m_rewardChest.Position = new Vector2(this.m_elf.X + 100f, (float)(this.m_elf.Bounds.Bottom - this.m_rewardChest.Height - 8)); } else { this.m_rewardChest.Position = new Vector2(this.m_elf.X - 150f, (float)(this.m_elf.Bounds.Bottom - this.m_rewardChest.Height - 8)); } this.m_rewardChest.Visible = false; base.GameObjList.Add(this.m_rewardChest); base.Initialize(); }
public void SetPhysicsObject(PhysicsObj obj) { PhysicsObj = obj; apply_current_movement(true, true); }
/// <summary> /// Starts the process of monster turning towards target /// </summary> public void StartTurn() { //if (Timers.RunningTime < NextMoveTime) //return; if (!MoveReady()) { return; } if (DebugMove) { Console.WriteLine($"{Name} ({Guid}) - StartTurn, ranged={IsRanged}"); } if (MoveSpeed == 0.0f) { GetMovementSpeed(); } //Console.WriteLine($"[{Timers.RunningTime}] - {Name} ({Guid}) - starting turn"); IsTurning = true; // send network actions var targetDist = GetDistanceToTarget(); var turnTo = IsRanged || (CurrentAttack == CombatType.Magic && targetDist <= GetSpellMaxRange()); if (turnTo) { TurnTo(AttackTarget); } else { MoveTo(AttackTarget, RunRate); } // need turning listener? IsTurning = false; IsMoving = true; LastMoveTime = Timers.RunningTime; NextCancelTime = LastMoveTime + ThreadSafeRandom.Next(2, 4); var mvp = GetMovementParameters(); if (turnTo) { PhysicsObj.TurnToObject(AttackTarget.PhysicsObj.ID, mvp); } else { PhysicsObj.MoveToObject(AttackTarget.PhysicsObj, mvp); } if (!InitSticky) { PhysicsObj.add_moveto_listener(OnMoveComplete); PhysicsObj.add_sticky_listener(OnSticky); PhysicsObj.add_unsticky_listener(OnUnsticky); InitSticky = true; } }
public static MotionInterp Create(PhysicsObj obj, WeenieObject wobj) { var motionInterp = new MotionInterp(obj, wobj); return(motionInterp); }
/// <summary> /// Primary dispatch for monster think /// </summary> public void Monster_Tick(double currentUnixTime) { if (IsChessPiece && this is GamePiece gamePiece) { // faster than vtable? gamePiece.Tick(currentUnixTime); return; } if (IsPassivePet && this is Pet pet) { pet.Tick(currentUnixTime); return; } NextMonsterTickTime = currentUnixTime + monsterTickInterval; if (!IsAwake) { if (MonsterState == State.Return) { MonsterState = State.Idle; } if (IsFactionMob) { FactionMob_CheckMonsters(); } return; } if (IsDead) { return; } HandleFindTarget(); CheckMissHome(); // tickrate? if (AttackTarget == null && MonsterState != State.Return) { Sleep(); return; } if (MonsterState == State.Return) { Movement(); return; } var combatPet = this as CombatPet; var creatureTarget = AttackTarget as Creature; if (creatureTarget != null && (creatureTarget.IsDead || (combatPet == null && !IsVisibleTarget(creatureTarget)))) { FindNextTarget(); return; } if (firstUpdate) { if (CurrentMotionState.Stance == MotionStance.NonCombat) { DoAttackStance(); } if (IsAnimating) { //PhysicsObj.ShowPendingMotions(); PhysicsObj.update_object(); return; } firstUpdate = false; } // select a new weapon if missile launcher is out of ammo var weapon = GetEquippedWeapon(); /*if (weapon != null && weapon.IsAmmoLauncher) * { * var ammo = GetEquippedAmmo(); * if (ammo == null) * SwitchToMeleeAttack(); * }*/ if (weapon == null && CurrentAttack != null && CurrentAttack == CombatType.Missile) { EquipInventoryItems(true); DoAttackStance(); CurrentAttack = null; } // decide current type of attack if (CurrentAttack == null) { CurrentAttack = GetNextAttackType(); MaxRange = GetMaxRange(); //if (CurrentAttack == AttackType.Magic) //MaxRange = MaxMeleeRange; // FIXME: server position sync } if (PhysicsObj.IsSticky) { UpdatePosition(); } // get distance to target var targetDist = GetDistanceToTarget(); //Console.WriteLine($"{Name} ({Guid}) - Dist: {targetDist}"); if (CurrentAttack != CombatType.Missile) { if (targetDist > MaxRange || (!IsFacing(AttackTarget) && !IsSelfCast())) { // turn / move towards if (!IsTurning && !IsMoving) { StartTurn(); } else { Movement(); } } else { // perform attack if (AttackReady()) { Attack(); } } } else { if (IsTurning || IsMoving) { Movement(); return; } if (!IsFacing(AttackTarget)) { StartTurn(); } else if (targetDist <= MaxRange) { // perform attack if (AttackReady()) { Attack(); } } else { // monster switches to melee combat immediately, // if target is beyond max range? // should ranged mobs only get CurrentTargets within MaxRange? //Console.WriteLine($"{Name}.MissileAttack({AttackTarget.Name}): targetDist={targetDist}, MaxRange={MaxRange}, switching to melee"); TrySwitchToMeleeAttack(); } } // pets drawing aggro if (combatPet != null) { combatPet.PetCheckMonsters(); } }
public override void Dispose() { if (!base.IsDisposed) { this.m_castleGate = null; this.m_teleporter = null; this.m_bossDoor = null; this.m_bossDoorSprite = null; this.m_diary = null; this.m_speechBubble = null; this.m_mapText = null; this.m_mapIcon = null; base.Dispose(); } }
public override void Dispose() { if (!base.IsDisposed) { this.m_targetList.Clear(); this.m_targetList = null; this.m_elf = null; this.m_axeIcons = null; this.m_gate = null; for (int i = 0; i < this.m_targetText.Count; i++) { this.m_targetText[i].Dispose(); this.m_targetDataText[i].Dispose(); } this.m_targetText.Clear(); this.m_targetText = null; this.m_targetDataText.Clear(); this.m_targetDataText = null; this.m_balloonList.Clear(); this.m_balloonList = null; this.m_rewardChest = null; base.Dispose(); } }