public void DropUnconscious(long duration = -1, bool toFront = true) { var cat = AniCatalog.Unconscious; ScriptAniJob job = toFront ? cat.DropFront : cat.DropBack; if (job != null) { ModelInst.StartAniJob(job); } _Uncon = toFront ? Unconsciousness.Front : Unconsciousness.Back; var strm = BaseInst.GetScriptVobStream(); strm.Write((byte)ScriptVobMessageIDs.Uncon); strm.Write((byte)_Uncon); BaseInst.SendScriptVobStream(strm); if (duration >= 0) { if (unconTimer == null) { unconTimer = new GUCTimer(LiftUnconsciousness); } unconTimer.SetInterval(duration); unconTimer.Start(); } OnUnconChange?.Invoke(this); }
public void DoVoice(VoiceCmd cmd, bool shout = false) { var strm = BaseInst.GetScriptVobStream(); strm.Write((byte)(shout ? ScriptVobMessageIDs.VoiceShout : ScriptVobMessageIDs.Voice)); strm.Write((byte)cmd); BaseInst.SendScriptVobStream(strm); }
private void DoLiftUncon() { _Uncon = Unconsciousness.None; var strm = BaseInst.GetScriptVobStream(); strm.Write((byte)ScriptVobMessageIDs.Uncon); strm.Write((byte)_Uncon); BaseInst.SendScriptVobStream(strm); int hp = HP + 25; SetHealth(hp > HPMax ? HPMax : hp); OnUnconChange?.Invoke(this); }
public void Hit(NpcInst attacker, int damage, bool fromFront = true) { var strm = BaseInst.GetScriptVobStream(); strm.Write((byte)ScriptVobMessageIDs.HitMessage); strm.Write((ushort)attacker.ID); BaseInst.SendScriptVobStream(strm); int protection = Protection; var armor = GetArmor(); if (armor != null) { protection += armor.Protection; } // two weapons ItemInst otherMelee; if ((otherMelee = GetLeftHand()) != null && otherMelee.ItemType == ItemTypes.Wep1H) { protection -= otherMelee.Damage / 4; } damage -= protection; if (damage <= 0) { damage = 1; } int resultingHP = GetHealth() - damage; if (DropUnconsciousOnDeath && resultingHP <= 1) { resultingHP = 1; DropUnconscious(UnconsciousDuration, !fromFront); } SetHealth(resultingHP); sOnHit?.Invoke(attacker, this, damage); OnHit?.Invoke(attacker, this, damage); LastHitMove = GameTime.Ticks; }
public void DoClimb(ClimbMoves move, NPC.ClimbingLedge ledge) { ScriptAniJob job; switch (move) { case ClimbMoves.High: job = AniCatalog.Climbs.High; break; case ClimbMoves.Mid: job = AniCatalog.Climbs.Mid; break; case ClimbMoves.Low: job = AniCatalog.Climbs.Low; break; default: Logger.Log("Not existing climb move: " + move); return; } if (job == null) { return; } var stream = BaseInst.GetScriptVobStream(); stream.Write((byte)ScriptVobMessageIDs.Climb); ledge.WriteStream(stream); BaseInst.SendScriptVobStream(stream); IsClimbing = true; ModelInst.StartAniJob(job, () => IsClimbing = false); }
private void CalcHit() { try { if (IsDead || FightAnimation == null || IsUnconscious) { return; } Vec3f attPos = GetPosition(); Angles attAng = GetAngles(); int baseDamage = 5 + Damage; ItemInst weapon; if ((weapon = GetDrawnWeapon()) != null) { baseDamage += weapon.Damage; } // two weapons if ((weapon = GetLeftHand()) != null && weapon.ItemType == ItemTypes.Wep1H) { baseDamage += weapon.Damage / 4; } float weaponRange = GetFightRange(); BaseInst.World.ForEachNPCRough(attPos, GUCScripts.BiggestNPCRadius + weaponRange, npc => // fixme: enemy model radius { NpcInst target = (NpcInst)npc.ScriptObject; if (target == this || target.IsDead || target.IsUnconscious) { return; } if (!AllowHitEvent.TrueForAll(this, target) || !AllowHitAttacker.TrueForAll(this, target) || !target.AllowHitTarget.TrueForAll(this, target)) { return; } float realRange = weaponRange + target.ModelDef.Radius; if (target.CurrentFightMove == FightMoves.Dodge) { realRange /= 3.0f; // decrease radius if target is backing up } Vec3f targetPos = npc.Position + npc.GetAtVector() * target.ModelDef.CenterOffset; if ((targetPos - attPos).GetLength() > realRange) { return; // not in range } float hitHeight; float hitYaw; if (CurrentFightMove == FightMoves.Left || CurrentFightMove == FightMoves.Right) { hitHeight = target.ModelDef.HalfHeight; hitYaw = Angles.PI * 0.4f; } else { hitHeight = target.ModelDef.HalfHeight + ModelDef.HalfHeight; hitYaw = Angles.PI * 0.2f; } if (Math.Abs(targetPos.Y - attPos.Y) > hitHeight) { return; // not same height } float yaw = Angles.GetYawFromAtVector(targetPos - attPos); if (Math.Abs(Angles.Difference(yaw, attAng.Yaw)) > hitYaw) { return; // target is not in front of attacker } float tdiff = Math.Abs(Angles.Difference(target.GetAngles().Yaw, yaw)); if (target.CurrentFightMove == FightMoves.Parry && tdiff > Angles.PI / 2) // parry 180 degrees { var strm = BaseInst.GetScriptVobStream(); strm.Write((byte)ScriptVobMessageIDs.ParryMessage); strm.Write((ushort)npc.ID); BaseInst.SendScriptVobStream(strm); } else // HIT { int damage = baseDamage; if (CurrentFightMove == FightMoves.Left || CurrentFightMove == FightMoves.Right) { damage -= 2; } else if (CurrentFightMove == FightMoves.Fwd) { damage += (ComboNum - 1) * 2; } else if (CurrentFightMove == FightMoves.Run) { damage += 6; if (Environment.InAir) // super jump attack { damage += 2; // not too much because you can always jump } if (target.Environment.InAir) { damage += 2; } } bool frontAttack; if (tdiff < Angles.PI / 4) // backstab { damage += 4; frontAttack = false; } else { frontAttack = true; } target.Hit(this, damage, frontAttack); } }); } catch (Exception e) { Logger.Log("CalcHit of npc " + ID + " " + BaseInst.HP + " " + e); } }