/// <summary> /// Checks for block if holding shield. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <returns></returns> static bool CheckShieldBlock( CharData ch, CharData victim ) { if( !victim.HasSkill( "shield block" ) ) return false; if( ch.IsAffected( Affect.AFFECT_DAZZLE ) ) return false; if( !victim.IsAwake() || victim.CurrentPosition < Position.reclining ) return false; Object obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_one ); if( !obj || ( obj.ItemType != ObjTemplate.ObjectType.shield ) ) { if( !( obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_two ) ) ) return false; if( obj.ItemType != ObjTemplate.ObjectType.shield ) return false; } if( obj.ItemType != ObjTemplate.ObjectType.shield ) { if( !( obj = Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_two ) ) ) return false; if( obj.ItemType != ObjTemplate.ObjectType.shield ) return false; } int chance = ch.GetSkillChance("shield block"); victim.PracticeSkill("shield block"); if (MUDMath.NumberPercent() >= ((chance - ch.Level) / 2)) { return false; } switch( MUDMath.NumberRange( 1, 5 ) ) { case 1: SocketConnection.Act( "You block $n&n's attack with your shield.", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n blocks your attack with a shield.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "$N&n blocks $n&n's attack with a shield.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); break; case 2: // If we were really smart we would check to see whether both the shield // and weapon were made of metal before we gave a sparks message... SocketConnection.Act( "&+CS&n&+cp&+Car&n&+ck&+Cs&n fly off your shield as you block $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n defends against your attack with a shield.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "$N&n deflects $n&n's attack with a shield.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); break; case 3: SocketConnection.Act("You bring up your shield to block $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$N&n brings up %s shield to block your attack.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$N&n brings up %s shield to blocks $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict); break; case 4: SocketConnection.Act("You knock $n&n's attack aside with your shield.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$N&n knocks your attack aside with $S shield.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$N&n knocks $n&n's attack aside with $S shield.", ch, null, victim, SocketConnection.MessageTarget.room_vict); break; case 5: SocketConnection.Act("You hear a thud as $n&n's weapon smacks into your shield.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("Your weapon smacks into $N&n's shield with a thud.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n's weapon smacks into $N&'s shield with a thud.", ch, null, victim, SocketConnection.MessageTarget.room_vict); break; default: break; } if( ch.Fighting == null ) SetFighting( ch, victim ); if( victim.Fighting == null ) SetFighting( victim, ch ); return true; }
public static void Aware(CharData ch, string[] str) { if( ch == null ) return; Affect af = new Affect(); if (ch.IsNPC()) return; if (!ch.HasSkill("awareness")) { ch.SendText("Your general obliviousness prevents your use of this skill.\r\n"); return; } if (ch.IsAffected(Affect.AFFECT_SKL_AWARE)) { ch.SendText("You are already about as tense as you can get.\r\n"); return; } ch.SendText("You try to become more aware of your surroundings.\r\n"); ch.PracticeSkill("awareness"); af.Value = "awareness"; af.Type = Affect.AffectType.skill; af.Duration = (ch.Level / 3) + 3; af.SetBitvector(Affect.AFFECT_SKL_AWARE); ch.AddAffect(af); return; }
/* * Modified to up the damage and allow for a * chance to stun victim or self * damage = (level) d2, for an average of 75 hp at level 50 * stun damage = (level) d3, for an average of 100 hp at level 50 * Player vs player damage is reduced in damage() */ /// <summary> /// Headbutt. Usable to initiate combat and during combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Headbutt(CharData ch, string[] str) { if( ch == null ) return; int chance; int ko; string text; /* Check player's level and class, mobs can use this skill */ if ((!ch.HasSkill("headbutt"))) { ch.SendText("Your skull is much too soft to headbutt anyone.\r\n"); return; } if (ch.IsBlind()) { return; } CharData victim = ch.Fighting; if (str.Length != 0) { if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead) { ch.SendText("They are nowhere to be seen.\r\n"); return; } } else { if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("You aren't fighting anyone.\r\n"); return; } } /* anti headbutt me code */ if (ch == victim) { ch.SendText("You get dizzy as you ponder the mechanics of headbutting yourself.\r\n"); return; } if (ch.CurrentPosition < Position.fighting) { ch.SendText("You need to stand up to do that.\r\n"); return; } /* Check size of ch vs. victim. */ /* If ch is too small. */ /* Made it 2 sizes */ if (ch.CurrentSize - 2 > victim.CurrentSize) { SocketConnection.Act("You would crush such a small and delicate being with your mass.", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* Ch 2 or more sizes larger than victim => bad! */ if (ch.CurrentSize + 1 < victim.CurrentSize) { SocketConnection.Act("You can't reach their head!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n slams $s head into your thigh.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n slams $s head into $N's thigh.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.WaitState((Skill.SkillList["headbutt"].Delay * 9) / 10); if (victim.Fighting == null) { Combat.SetFighting(victim, ch); } return; } ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["headbutt"].Delay)); ch.PracticeSkill("headbutt"); if (!ch.Fighting) { Combat.SetFighting(ch, victim); } if (!victim.Fighting) { Combat.SetFighting(victim, ch); } /* Added a PC skill level */ // Chance was over-downgraded at some point. Was skill level - 5%, // then it was changed to skill level / 2 giving a level 50 a headbutt // success rate of about 47%. I've upped it to 4/5 of skill level, // meaning that a level 50 has a success rate of 76%, which is a good // target success rate. Keep in mind minotaur will have a success rate of // about 83%. if (ch.IsNPC()) { chance = 50 + ch.Level; } else { chance = ((PC)ch).SkillAptitude["headbutt"] * 4 / 5; } // Minotaur headbutt bonus if (ch.GetRace() == Race.RACE_MINOTAUR) { chance += 7; } if (victim.CurrentPosition < Position.fighting) { chance /= 3; } if (MUDMath.NumberPercent() < chance) /* Headbutt successful, possible KO */ { /* First give the victim a chance to dodge */ if (Combat.CheckDodge(ch, victim)) { return; } /* OK, lets settle for stun right now * a skill level of 100% has a 20% chance of stun * a skill level of 50% has a 2.5% chance of stun * a skill level of 23% has a 1% chance of stun * immortals get a 15% bonus */ // The stun math was bad. Stun was way more often that it should have // been. Now we have a flat /4 chance, meaning a the following stun chances // at each skill level: // 25 = 5% 50 = 10 % 75 = 15% 95 = 19% ko = chance / 4; if (ch.IsImmortal()) { ko += 15; } text = String.Format("Commandheadbutt: {0}&n attempting a KO with {1}%% chance.", ch.Name, ko); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, text); if (MUDMath.NumberPercent() < ko + 1) { // deal some decent damage // This was previously level d 3 which was fairly pathetic. // Level d 8 = 50 min, 400 max at level 50 with an average of 225 // PvP damage is quartered, so headbutt will do about 56 against a player. if (ch.GetRace() != Race.RACE_MINOTAUR) { Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 8), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } else { Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 9), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } if (victim.CurrentPosition > Position.stunned) { SocketConnection.Act("$n&n staggers about, then collapses in a heap.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You fall to the ground &+Wstunned&n.\r\n"); SocketConnection.Act("$n&n is &+Wstunned!&n", victim, null, null, SocketConnection.MessageTarget.room); victim.CurrentPosition = Position.stunned; victim.WaitState((Skill.SkillList["headbutt"].Delay)); text = String.Format("Commandheadbutt: {0}&n stunned {1}&n.", ch.Name, victim.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, text); } } else { // just your ordinary headbutt damage // This was previously level d 2 which was fairly pathetic. // Level d 6 = 50 min, 300 max at level 50 with an average of 175 // PvP damage is quartered, so headbutt will do about 43 against a player. if (ch.GetRace() != Race.RACE_MINOTAUR) { if (!Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 6), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon)) { // Someone blasts you in the head it'll definitely stun you for 3/4 of a second. victim.WaitState(3); } } else { if (!Combat.InflictDamage(ch, victim, MUDMath.Dice(ch.Level, 7), "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon)) { // Someone blasts you in the head with horns it'll definitely stun you for a second. // -- Xangis victim.WaitState(4); } } } } else /* Headbutt failed, possible damgage to self, possible KO of self */ { /* Don't allow char to kill self, just mort self */ /* Give them a chance to not take any damage */ // Checking chance instead of player's level. Since this should be based on skill // this should be about right (average of 24% chance of screwing yourself at level 50 // instead of 50%, 17% chance for minos). if (MUDMath.NumberPercent() < chance) { ch.SendText("Your headbutt fails to strike its target.\r\n"); SocketConnection.Act("$n&n tries to headbutt $N&n but can't quite connect.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n bobs around you in a feeble attempt at a headbutt.", ch, null, victim, SocketConnection.MessageTarget.victim); return; } SocketConnection.Act("You bang your head against the brick wall of $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n tries a headbutt but $N&n gets the best of $m.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n bangs into you in a feeble attempt at a headbutt.", ch, null, victim, SocketConnection.MessageTarget.victim); // KO chance of 24% for normals, 17% for minos. // You have to fail three checks to get your ass kicked by KO, one for the actual skill check, // one for the damage check and finally one for the KO check. // keep in mind this KO does damage of about 100 to self at level 50, which is a hell of a lot // for a failed skill. // The chance of ko'ing yourself at each skill level is as follows: (after all 3 checks) // Skill 25 = 59.2% Skill 50 = 29.6% Skill 75 = 14.4% Skill 95 = 9.38% ko = 108 - chance; int dam; if (MUDMath.NumberPercent() < ko) { // doh! This is gonna hurt //deal some decent damage...to self! if (ch.GetRace() != Race.RACE_MINOTAUR) { dam = MUDMath.Dice(ch.Level, 3); } else { dam = MUDMath.Dice(ch.Level, 2); } if (dam > ch.Hitpoints) { dam = ch.Hitpoints + 1; } if (Combat.InflictDamage(ch, ch, dam, "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon)) { // ch invalidated, can't send messages. return; } SocketConnection.Act("$n&n staggers about, then collapses in a heap.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You fall to the ground stunned.\r\n"); SocketConnection.Act("$n&n is stunned!", ch, null, null, SocketConnection.MessageTarget.room); ch.CurrentPosition = Position.stunned; ch.WaitState((Skill.SkillList["headbutt"].Delay * 2)); text = String.Format("Commandheadbutt: {0}&n stunned self.", ch.Name); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, text); } else { // Was previously level d 2, which averaged 30 damage at 20 and 75 at 50. PC to PC // damage is not quartered when it is done to yourself, so this it kind of high at the // upper levels. This has been reduced by level / 5, so the damage at 50 averages 65 // instead of 65. // Keep in mind that the real penalties come from KO and comparitively someone that // fails a bash doesen't take insane damage. dam = MUDMath.Dice(ch.Level, 2) - ch.Level / 5; if (dam > ch.Hitpoints) { dam = ch.Hitpoints + 1; } Combat.InflictDamage(ch, ch, dam, "headbutt", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } } //end if() headbutt failed return; }
/// <summary> /// Throw dirt in someone's eyes. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void DirtToss(CharData ch, string[] str) { if( ch == null ) return; int percent; /* Don't allow the unskilled to do this, check player's level */ if (!ch.HasSkill("dirt toss")) { ch.SendText("You get your feet dirty.\r\n"); return; } if (ch.IsBlind()) { ch.SendText("You can't see anything!\r\n"); return; } if (ch.FlightLevel != 0) { ch.SendText("Perhaps you should land first matey.\r\n"); return; } CharData victim = ch.Fighting; if (str.Length != 0) { if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead) { ch.SendText("They aren't here.\r\n"); return; } } if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("You aren't fighting anyone.\r\n"); return; } if (victim == ch) { ch.SendText("How about sticking a fork your eye instead?\r\n"); return; } if (victim.IsAffected( Affect.AFFECT_BLIND)) { SocketConnection.Act("$E's already been &+Lblinded&n.", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (!ch.IsNPC()) { percent = ((PC)ch).SkillAptitude["dirt toss"]; } else { percent = (ch.Level * 3) / 2 + 25; } percent += (ch.Level - victim.Level) * 2; percent += (ch.GetCurrDex() / 10); percent -= (victim.GetCurrDex() / 10); percent -= (victim.GetCurrAgi() / 10); // Why waste time listing sectors with no modifier? switch (ch.InRoom.TerrainType) { case TerrainType.inside: case TerrainType.arctic: case TerrainType.swamp: percent -= 20; break; case TerrainType.city: case TerrainType.mountain: percent -= 10; break; case TerrainType.plane_of_fire: case TerrainType.plane_of_air: case TerrainType.plane_of_water: case TerrainType.plane_ethereal: case TerrainType.plane_astral: case TerrainType.underwater_has_ground: case TerrainType.underwater_no_ground: case TerrainType.swimmable_water: case TerrainType.unswimmable_water: case TerrainType.air: case TerrainType.ocean: case TerrainType.underground_swimmable_water: case TerrainType.underground_unswimmable_water: percent = 0; break; case TerrainType.field: percent += 5; break; case TerrainType.desert: percent += 10; break; case TerrainType.plane_of_earth: percent += 15; break; default: break; } if (percent > 75) { percent = 75; } else if (percent < 5) { percent = 5; } if (percent <= 0) { ch.SendText("There isn't any &n&+ydirt&n to kick.\r\n"); return; } ch.PracticeSkill("dirt toss"); if (percent < MUDMath.NumberPercent()) { Affect af = new Affect(); SocketConnection.Act("$n is &+Lblinded&n by the &n&+ydirt&n in $s eyes!", victim, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("$n kicks &n&+ydirt&n into your eyes!", ch, null, victim, SocketConnection.MessageTarget.victim); victim.SendText("&+LYou can't see a thing!&n\r\n"); af.Value = "dirt toss"; af.Type = Affect.AffectType.skill; af.Duration = MUDMath.NumberRange(1, 2); af.AddModifier(Affect.Apply.hitroll, -4); af.SetBitvector(Affect.AFFECT_BLIND); victim.AddAffect(af); } else { ch.SendText("&+LYou kick dirt at your target!&n\r\n"); } Combat.SetFighting(victim, ch); ch.WaitState(Skill.SkillList["dirt toss"].Delay); return; }
/// <summary> /// Knock a door from its hinges with brute force. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void DoorBash(CharData ch, string[] str) { if( ch == null ) return; Exit.Direction door; Room toRoom; if (ch.IsNPC() || (!ch.HasSkill("doorbash") && !ch.HasInnate(Race.RACE_DOORBASH))) { ch.SendText("You don't feel massive enough!\r\n"); return; } if (str.Length == 0) { ch.SendText("Doorbash what?\r\n"); return; } if (ch.Fighting) { ch.SendText("You can't break off your fight.\r\n"); return; } if ((door = Movement.FindDoor(ch, str[0])) >= 0) { Exit reverseExit; int chance; Exit exit = ch.InRoom.GetExit(door); if (!exit.HasFlag(Exit.ExitFlag.closed)) { ch.SendText("Calm down. It is already open.\r\n"); return; } ch.WaitState(Skill.SkillList["doorbash"].Delay); if (ch.IsNPC()) { chance = 0; } else if (!ch.HasSkill("doorbash")) { chance = 20; } else { chance = ((PC)ch).SkillAptitude["doorbash"] / 2; } if (exit.HasFlag(Exit.ExitFlag.locked)) { chance /= 2; } if (exit.HasFlag(Exit.ExitFlag.bashproof) && !ch.IsImmortal()) { SocketConnection.Act("WHAAAAM!!! You bash against the $d, but it doesn't budge.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character); SocketConnection.Act("WHAAAAM!!! $n&n bashes against the $d, but it holds strong.", ch, null, exit.Keyword, SocketConnection.MessageTarget.room); Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 20), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); if (exit.HasFlag(Exit.ExitFlag.spiked)) { SocketConnection.Act("You are impaled by spikes protruding from the $d!", ch, null, exit.Keyword, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n is impaled by spikes protruding from the $d!", ch, null, exit.Keyword, SocketConnection.MessageTarget.room); Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 5), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.pierce); } return; } if (exit.HasFlag(Exit.ExitFlag.spiked)) { SocketConnection.Act("You are impaled by spikes protruding from the $d!", ch, null, exit.Keyword, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n is impaled by spikes protruding from the $d!", ch, null, exit.Keyword, SocketConnection.MessageTarget.room); Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 5), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.pierce); } if ((ch.GetCurrStr() >= 20) && MUDMath.NumberPercent() < (chance + 4 * (ch.GetCurrStr() - 20))) { /* Success */ exit.RemoveFlag(Exit.ExitFlag.closed); if (exit.HasFlag(Exit.ExitFlag.locked)) { exit.RemoveFlag(Exit.ExitFlag.locked); } exit.AddFlag(Exit.ExitFlag.bashed); SocketConnection.Act("Crash! You bashed open the $d!", ch, null, exit.Keyword, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n bashes open the $d!", ch, null, exit.Keyword, SocketConnection.MessageTarget.room); Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 30), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); /* Bash through the other side */ if ((toRoom = Room.GetRoom(exit.IndexNumber)) && (reverseExit = toRoom.GetExit(Exit.ReverseDirection(door))) && reverseExit.TargetRoom == ch.InRoom) { reverseExit.RemoveFlag(Exit.ExitFlag.closed); if (reverseExit.HasFlag(Exit.ExitFlag.locked)) { reverseExit.RemoveFlag(Exit.ExitFlag.locked); } reverseExit.AddFlag(Exit.ExitFlag.bashed); foreach (CharData irch in toRoom.People) { SocketConnection.Act("The $d crashes open!", irch, null, reverseExit.Keyword, SocketConnection.MessageTarget.character); } // Have any aggro mobs on the other side come after the player. foreach (CharData charData in toRoom.People) { if (charData != ch && (charData.IsNPC() && !charData.IsAffected( Affect.AFFECT_CHARM)) && charData.IsAggressive(ch) && charData.IsAwake() && CharData.CanSee(charData, ch) && !charData.Fighting) { Combat.StartHating(charData, ch); Combat.StartHunting(charData, ch); } } } } else { /* Failure */ SocketConnection.Act("OW! You bash against the $d, but it doesn't budge.", ch, null, exit.Keyword, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n bashes against the $d, but it holds strong.", ch, null, exit.Keyword, SocketConnection.MessageTarget.room); Combat.InflictDamage(ch, ch, (ch.GetMaxHit() / 10), "doorbash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } } /* * Check for "guards"... anyone bashing a door is considered as * a potential aggressor, and there's a 25% chance that mobs * will do unto before being done unto. * But first...let's make sure ch ain't dead? That'd be a pain. */ if (ch.Hitpoints <= 1) return; ch.PracticeSkill("doorbash"); foreach (CharData guardChar in ch.InRoom.People) { if (guardChar != ch && guardChar.HasActionBit(MobTemplate.ACT_PROTECTOR) && (guardChar.IsNPC() && !guardChar.IsAffected( Affect.AFFECT_CHARM)) && guardChar.IsAwake() && CharData.CanSee(guardChar, ch) && !guardChar.Fighting && MUDMath.NumberBits(2) == 0) { SocketConnection.Act("$n&n is very unhappy about you trying to destroy the door.", guardChar, null, ch, SocketConnection.MessageTarget.victim); guardChar.AttackCharacter(ch); } } return; }
/// <summary> /// Try to free someone who has been bound. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Untangle(CharData ch, string[] str) { if( ch == null ) return; CharData victim; if (!ch.IsNPC() && !ch.HasSkill("untangle")) { ch.SendText("You aren't nimble enough.\r\n"); return; } if (str.Length == 0) { victim = ch; } else { victim = ch.GetCharRoom(str[0]); if (victim == null) { ch.SendText("They aren't here.\r\n"); return; } } if (!victim.HasAffect( Affect.AffectType.skill, "capture")) { ch.SendText("There's nothing to untangle.\r\n"); return; } if ((ch.IsNPC() && !ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["untangle"])) { victim.AffectStrip( Affect.AffectType.skill, "capture"); if (victim != ch) { SocketConnection.Act("You untangle $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n untangles you.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n untangles $n&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { ch.SendText("You untangle yourself.\r\n"); SocketConnection.Act("$n&n untangles $mself.", ch, null, null, SocketConnection.MessageTarget.room); } ch.PracticeSkill("untangle"); return; } }
/// <summary> /// Zap a wand, using its spell power. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Zap(CharData ch, string[] str) { if( ch == null ) return; Object wand = null; Object obj = null; CharData victim; int level; if (str.Length == 0 && ch.Fighting == null) { ch.SendText("Zap whom or what?\r\n"); return; } if (!String.IsNullOrEmpty(str[0]) && !(wand = ch.GetObjWear(str[0]))) { if (!(wand = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one))) { ch.SendText("You hold nothing in your hand.\r\n"); return; } } else /* Wand was first argument.. arg is now second argument. */ if (wand.ItemType != ObjTemplate.ObjectType.wand) { ch.SendText("You can zap only with a wand.\r\n"); return; } level = wand.Level; if (String.IsNullOrEmpty(str[0])) { if (ch.Fighting != null) { victim = ch.Fighting; } else { ch.SendText("Zap whom or what?\r\n"); return; } } else { if (((victim = ch.GetCharRoom(str[0])) == null) && (obj = ch.GetObjHere(str[0])) == null) { ch.SendText("You can't find your _targetType.\r\n"); return; } } if (ch.IsNPC() && !ch.IsFreewilled()) { SocketConnection.Act("You try to zap $p&n, but you have no free will.", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n tries to zap $p&n, but has no free will.", ch, wand, null, SocketConnection.MessageTarget.room); return; } String spellName = SpellNumberToTextMap.GetSpellNameFromNumber(wand.Values[3]); if (String.IsNullOrEmpty(spellName)) { ch.SendText("You try to zap, but your wand fizzles.\r\n"); Log.Error("Zap: Spell number " + wand.Values[3] + " not found in SpellNumberToTextMap for object " + wand.ObjIndexNumber + "."); return; } Spell spell = StringLookup.SpellLookup(spellName); if (!spell) { ch.SendText("You try to zap, but your wand fizzles.\r\n"); Log.Error("Zap: Spell '" + spellName + "' not found for object " + wand.ObjIndexNumber + ". Check that it exists in the spells file."); return; } ch.PracticeSkill("wands"); if (wand.Values[2] > 0) { if (victim != null) { if (victim == ch) { SocketConnection.Act("You zap yourself with $p&n.", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n zaps $mself with $p&n.", ch, wand, null, SocketConnection.MessageTarget.room); } else { SocketConnection.Act("You zap $N&n with $p&n.", ch, wand, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n zaps $N&n with $p&n.", ch, wand, victim, SocketConnection.MessageTarget.room); } } else { SocketConnection.Act("You zap $P&n with $p&n.", ch, wand, obj, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n zaps $P&n with $p&n.", ch, wand, obj, SocketConnection.MessageTarget.room); } if (!ch.IsNPC() && (MUDMath.NumberPercent() > ((PC)ch).SkillAptitude["wands"])) { switch (MUDMath.NumberBits(3)) { case 0: case 1: case 2: case 3: SocketConnection.Act("You are unable to invoke the power of $p&n.", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n is unable to invoke the power of $p&N.", ch, wand, null, SocketConnection.MessageTarget.room); break; case 4: case 5: case 6: SocketConnection.Act("You summon the power of $p&n, but it fizzles away.", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n summons the power of $p&n, but it fizzles away.", ch, wand, null, SocketConnection.MessageTarget.room); break; case 7: SocketConnection.Act("You can't control the power of $p&n, and it &+Rexplodes&n!", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n &n&+rexplodes&n into fragments!", ch, wand, null, SocketConnection.MessageTarget.room); /* * Command.damage( ) call after Object.extract_obj in case the damage would * have extracted ch. This is okay because we merely mark * obj.deleted; it still retains all values until list_update. * Sloppy? Okay, create another integer variable. * I hate sloppy... */ wand.RemoveFromWorld(); Combat.InflictDamage(ch, ch, level, "wands", ObjTemplate.WearLocation.none, AttackType.DamageType.energy); break; } return; } Magic.ObjectCastSpell(ch, spell, level, victim, obj); } if (--(wand.Values[2]) <= 0) { if (!ch.IsNPC() && MUDMath.NumberPercent() > ((PC)ch).SkillAptitude["wands"]) { SocketConnection.Act("$p&n &n&+rexplodes&n into fragments.", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n &+Rexplodes&n into fragments.", ch, wand, null, SocketConnection.MessageTarget.room); wand.RemoveFromWorld(); Combat.InflictDamage(ch, ch, level, "wands", ObjTemplate.WearLocation.none, AttackType.DamageType.energy); } else { SocketConnection.Act("$p&n blazes bright and is gone.", ch, wand, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n blazes bright and is gone.", ch, wand, null, SocketConnection.MessageTarget.room); wand.RemoveFromWorld(); } } return; }
/// <summary> /// Pick a lock. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Pick(CharData ch, string[] str) { if( ch == null ) return; Object obj; Exit.Direction door; if (str.Length == 0) { ch.SendText("Pick what, your nose?\r\n"); return; } if (ch.Riding) { ch.SendText("You can't do that while mounted.\r\n"); return; } ch.WaitState(Skill.SkillList["pick lock"].Delay); // Look for guards or other mobs who could be "in the way". foreach (CharData charData in ch.InRoom.People) { if (charData.IsNPC() && charData.IsAwake() && ch.Level + 5 < charData.Level) { SocketConnection.Act("$N&n is standing too close to the lock.", ch, null, charData, SocketConnection.MessageTarget.character); return; } } // Check skill roll for player, make sure mob isn't charmed. if ((!ch.IsNPC() && MUDMath.NumberPercent() > ((PC)ch).SkillAptitude["pick lock"]) || (ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM))) { ch.PracticeSkill("pick lock"); ch.SendText("You failed.\r\n"); return; } if ((door = Movement.FindDoor(ch, str[0])) >= 0) { /* 'pick door' */ Exit reverseExit; Room toRoom; Exit exit = ch.InRoom.GetExit(door); if (!exit.HasFlag(Exit.ExitFlag.closed)) { ch.SendText("It's not closed.\r\n"); return; } if (exit.Key < 0) { ch.SendText("It can't be picked.\r\n"); return; } if (!exit.HasFlag(Exit.ExitFlag.locked)) { ch.SendText("It's already unlocked.\r\n"); return; } if (exit.HasFlag(Exit.ExitFlag.pickproof)) { ch.SendText("You failed.\r\n"); return; } exit.RemoveFlag(Exit.ExitFlag.locked); ch.SendText("*Click*\r\n"); SocketConnection.Act("$n&n picks the $d.", ch, null, exit.Keyword, SocketConnection.MessageTarget.room); /* pick the other side */ if ((toRoom = Room.GetRoom(exit.IndexNumber)) && (reverseExit = toRoom.GetExit(Exit.ReverseDirection(door))) && reverseExit.TargetRoom == ch.InRoom) { reverseExit.RemoveFlag(Exit.ExitFlag.locked); } return; } if ((obj = ch.GetObjHere(str[0]))) { /* 'pick portal' */ if (obj.ItemType == ObjTemplate.ObjectType.portal) { if (!Macros.IsSet(obj.Values[3], ObjTemplate.PORTAL_CLOSED)) { ch.SendText("It's not closed.\r\n"); return; } if (obj.Values[4] < 0) { ch.SendText("It can't be unlocked.\r\n"); return; } if (!Macros.IsSet(obj.Values[3], ObjTemplate.PORTAL_LOCKED)) { ch.SendText("It's already unlocked.\r\n"); return; } if (Macros.IsSet(obj.Values[3], ObjTemplate.PORTAL_PICKPROOF)) { ch.SendText("You failed.\r\n"); return; } Macros.RemoveBit(ref obj.Values[3], ObjTemplate.PORTAL_LOCKED); ch.SendText("*Click*\r\n"); SocketConnection.Act("$n&n picks $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); return; } /* 'pick object' */ if (obj.ItemType != ObjTemplate.ObjectType.container) { ch.SendText("That is not a container.\r\n"); return; } if (!Macros.IsSet(obj.Values[1], ObjTemplate.CONTAINER_CLOSED.Vector)) { ch.SendText("It's not closed.\r\n"); return; } if (obj.Values[2] < 0) { ch.SendText("It can't be unlocked.\r\n"); return; } if (!Macros.IsSet(obj.Values[1], ObjTemplate.CONTAINER_LOCKED.Vector)) { ch.SendText("It's already unlocked.\r\n"); return; } if (Macros.IsSet(obj.Values[1], ObjTemplate.CONTAINER_PICKPROOF.Vector)) { ch.SendText("You failed.\r\n"); return; } Macros.RemoveBit(ref obj.Values[1], ObjTemplate.CONTAINER_LOCKED.Vector); ch.SendText("*Click*\r\n"); SocketConnection.Act("$n&n picks $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); return; } return; }
/// <summary> /// Bodyslam an opponent. Can only be used to initiate combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Bodyslam(CharData ch, string[] str) { if( ch == null ) return; CharData victim; /* Check player's level and class, mobs can use this skill */ if (!ch.HasInnate(Race.RACE_BODYSLAM)) { ch.SendText("You don't feel massive enough to manhandle that.\r\n"); return; } if (ch.IsBlind()) { return; } if (ch.Riding) { ch.SendText("You can't do that while mounted.\r\n"); return; } if (str.Length != 0) { if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead) { ch.SendText("They aren't here.\r\n"); return; } } else { ch.SendText("Bodyslam who?\r\n"); return; } // Added size restrictions -- Xangis if (victim.CurrentSize > ch.CurrentSize) { if (ch.HasInnate(Race.RACE_SLAM_LARGER)) { // allowing centaurs to slam one size up if it's an ogre if (victim.CurrentSize > (ch.CurrentSize + 1)) { ch.SendText("You can't bodyslam something that much bigger than you.\r\n"); return; } } else { ch.SendText("You can't bodyslam something bigger than you.\r\n"); return; } } if ((ch.CurrentSize > victim.CurrentSize) && ((ch.CurrentSize - victim.CurrentSize) > 3)) { ch.SendText("They're too small to slam.\r\n"); return; } /* Bodyslam self? Ok! */ if (ch == victim) { ch.SendText("You slam yourself to the ground!\r\n"); SocketConnection.Act("$n&n throws $mself to the ground in a fit of clumsiness.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.WaitState((Skill.SkillList["bodyslam"].Delay / 2)); ch.CurrentPosition = Position.reclining; Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 6), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); return; } ch.WaitState(Skill.SkillList["bodyslam"].Delay); ch.PracticeSkill("bodyslam"); int chance = (ch.Level * 3) / 2 + 15; chance += ch.GetCurrAgi() - victim.GetCurrAgi(); chance -= (victim.Level - ch.Level); switch (victim.CurrentPosition) { case Position.dead: return; case Position.mortally_wounded: chance += 15; break; case Position.incapacitated: chance += 10; break; case Position.unconscious: chance += 5; break; case Position.stunned: chance += 3; break; case Position.sleeping: chance += 2; break; case Position.reclining: chance -= 45; break; case Position.resting: chance -= 30; break; case Position.sitting: chance -= 20; break; case Position.kneeling: chance -= 15; break; case Position.fighting: case Position.standing: default: break; } // Small penalty for the small buggers -- Xangis if (victim.CurrentSize < (ch.CurrentSize - 1)) { chance -= 15; } if (chance > 90) { chance = 90; } // Shaman bodyslam penalty. if (ch.IsClass(CharClass.Names.shaman) || ch.IsClass(CharClass.Names.druid)) { chance = (chance * 2) / 3; } if (victim.IsAffected(Affect.AFFECT_AWARE)) { chance -= 15; } else if (victim.IsAffected( Affect.AFFECT_SKL_AWARE)) { if (ch.HasSkill("springleap")) { if (ch.IsNPC()) { if (MUDMath.NumberPercent() < ((ch.Level * 3) / 2 + 15)) { chance -= 15; } } else if (MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["awareness"]) { ch.PracticeSkill("awareness"); chance -= 15; } else { ch.PracticeSkill("awareness"); } } } if (!ch.Fighting) { Combat.SetFighting(ch, victim); } if (victim.Fighting == null) { Combat.SetFighting(victim, ch); } if (ch.IsNPC() || MUDMath.NumberPercent() < chance) { if (victim.IsAffected( Affect.AFFECT_SINGING)) { victim.RemoveAffect(Affect.AFFECT_SINGING); SocketConnection.Act("$n&n suddenly loses track of the key $e was singing in.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You get the wind knocked out of you!\r\n"); } if (victim.IsAffected( Affect.AFFECT_CASTING)) { victim.RemoveAffect(Affect.AFFECT_CASTING); SocketConnection.Act("$n&n's thoughts of casting are scattered about as $e is slammed into the ground.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("Your brain slamming against your skull disrupts your concentration.\r\n"); } // Moved damage to bottom because it would crash when a person died, because // it still tried to access them as a valid character. Also added tumble check for // thieves. if (!Combat.CheckTumble(victim)) { victim.WaitState(Skill.SkillList["bodyslam"].Delay); victim.CurrentPosition = Position.reclining; Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } else { if (!Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "bodyslam", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon)) { ch.SendText("You roll with the blow, finally landing on your feet.\r\n"); SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", ch, null, null, SocketConnection.MessageTarget.room); } } } else { ch.Hitpoints -= MUDMath.NumberRange(1, 5); SocketConnection.Act("As $N&n avoids your slam, you smack headfirst into the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n throws $mself to the &n&+yground&n in a fit of clumsiness.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n misses a bodyslam on $N&n and slams $s head into the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.CurrentPosition = Position.reclining; } return; }
/// <summary> /// Kick someone. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Kick(CharData ch, string[] str) { if( ch == null ) return; int chance; int wallkickchance; /* Check player's level and class, allow mobs to do this too */ if ((!ch.HasSkill("kick"))) { ch.SendText("You'd better leave the martial arts to fighters.\r\n"); return; } if (ch.IsBlind() && !ch.Fighting) { return; } CharData victim = ch.Fighting; if (str.Length != 0) { victim = ch.GetCharRoom(str[0]); if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("They aren't here.\r\n"); return; } } else { if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("You aren't fighting anyone.\r\n"); return; } } if (victim == ch) { ch.SendText("You kick yourself for being a dummy.\r\n"); return; } ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["kick"].Delay)); if (!ch.IsNPC()) { chance = ((PC)ch).SkillAptitude["kick"]; ch.PracticeSkill("kick"); } else { chance = ch.Level * 3 / 2 + 20; } // It's much harder to kick really tiny things; imagine trying to kick // a fly. if (ch.CurrentSize > victim.CurrentSize + 5) { chance -= (ch.CurrentSize - victim.CurrentSize) * 5; } // It's harder to kick things that move faster than you. chance += ((ch.GetCurrAgi() - victim.GetCurrAgi()) / 5); // Huge bonus against incapacitated and mortally wounded foes. if (victim.CurrentPosition <= Position.incapacitated) { chance += 50; } // Damned high penalty for kicking blind if (ch.IsAffected(Affect.AFFECT_BLIND) && !victim.IsAffected(Affect.AFFECT_BLIND)) { chance /= 10; } if (ch.IsAffected(Affect.AFFECT_BLIND) && victim.IsAffected(Affect.AFFECT_BLIND)) { chance /= 4; } // If the victim is two or more sizes smaller than the kicker give them a chance // to be kicked into a wall or out of the room. // // Chance of 5% per size class difference, no maximum // (wall/room kick is 50% at a difference of 10 sizes) if (victim.CurrentSize - 1 >= ch.CurrentSize) { wallkickchance = 0; } else { wallkickchance = ((ch.CurrentSize - victim.CurrentSize) * 5) - 5; } // Check for kick success if (MUDMath.NumberPercent() < chance) { /* Check for wall kick. */ /* to be kicked out of the room (random direction). */ if (MUDMath.NumberPercent() < wallkickchance) { Exit.Direction door = Database.RandomDoor(); // Check for valid room stuff on victim Room kickedInto; Exit exit; if (victim && victim.InRoom && victim.InRoom.ExitData != null && (exit = victim.InRoom.GetExit(door)) && exit.TargetRoom && exit.ExitFlags != 0 && !exit.HasFlag(Exit.ExitFlag.secret) && !exit.HasFlag(Exit.ExitFlag.blocked) && !exit.HasFlag(Exit.ExitFlag.walled) && exit.HasFlag(Exit.ExitFlag.closed) && !Room.GetRoom(exit.IndexNumber).IsPrivate() && exit.TargetRoom.TerrainType != TerrainType.underground_impassable && (kickedInto = Room.GetRoom(exit.IndexNumber))) { Combat.StopFighting(victim, true); string buf = String.Format("$N&n is sent flying out of the room {0}ward by $n&n's mighty kick.", door.ToString()); SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.room_vict); buf = String.Format("$N&n is sent flying out of the room {0}ward by your mighty kick.", door.ToString()); SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("You are sent flying out of the room by $n's mighty kick!", ch, null, victim, SocketConnection.MessageTarget.victim); victim.RemoveFromRoom(); victim.AddToRoom(kickedInto); SocketConnection.Act("$n&n is stunned!", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You are stunned!\r\n"); victim.WaitState((Skill.SkillList["kick"].Delay * 9) / 10); if (victim.CurrentPosition > Position.resting) { victim.CurrentPosition = Position.resting; } } else { // If no exit in our chosen direction, must be a wall. SocketConnection.Act("$N&n is sent flying into the wall by $n&n's mighty kick.", ch, null, victim, SocketConnection.MessageTarget.room_vict); SocketConnection.Act("$N&n is sent flying into the wall by your mighty kick.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("You are smacked into the wall by $n's mighty kick!", ch, null, victim, SocketConnection.MessageTarget.victim); if (victim.CurrentPosition > Position.resting) { victim.CurrentPosition = Position.resting; } // At least a two second stun victim.WaitState(8); /* Check for stunning victim. */ if ((MUDMath.NumberPercent() * 2) > victim.GetCurrAgi()) { SocketConnection.Act("$N&n is stunned!", ch, null, victim, SocketConnection.MessageTarget.room_vict); victim.SendText("You are stunned!\r\n"); victim.WaitState((Skill.SkillList["kick"].Delay * 9) / 10); } else { victim.WaitState(1); } } // Do excessive damage compared to a normal kick Combat.InflictDamage(ch, victim, MUDMath.Dice(2, ch.Level), String.Empty, ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } // Check for wall kick (execute regular kick) else { Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "kick", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } } // Check for successful kick (missed kick) else { Combat.InflictDamage(ch, victim, 0, "kick", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } return; }
/// <summary> /// Meditate command. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Meditate(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (!ch.HasSkill("meditate")) { ch.SendText("You don't know how to meditate.\r\n"); return; } if (ch.HasActionBit(PC.PLAYER_MEDITATING)) { ch.RemoveActionBit(PC.PLAYER_MEDITATING); ch.SendText("You stop meditating.\r\n"); } if (ch.CurrentPosition != Position.resting) { ch.SendText("You must be resting in order to meditate.\r\n"); return; } if (ch.Fighting != null) { ch.SendText("Meditation during battle leads to permenant inner peace.\r\n"); return; } ch.SetActionBit(PC.PLAYER_MEDITATING); ch.WaitState(Skill.SkillList["meditate"].Delay); ch.PracticeSkill("meditate"); ch.SendText("You start meditating...\r\n"); return; }
/// <summary> /// Do one round of attacks for one character. /// Note: This is a round, not a single attack! /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <param name="skill"></param> /// <returns></returns> public static bool CombatRound(CharData ch, CharData victim, string skill) { Object wield; int chance = 0; if( ch == null ) { return false; } if( victim == null ) { return false; } /* No casting/being para'd and hitting at the same time. */ if( ( ch.IsAffected( Affect.AFFECT_CASTING ) ) || ch.IsAffected( Affect.AFFECT_MINOR_PARA ) || ch.IsAffected(Affect.AFFECT_HOLD)) { return false; } /* I don't know how a dead person can hit someone/be hit. */ if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 ) { StopFighting( victim, true ); return true; } /* * Set the fighting fields now. */ if( victim.CurrentPosition > Position.stunned ) { if( !victim.Fighting ) SetFighting( victim, ch ); // Can't have bashed/prone people just automatically be standing. if( victim.CurrentPosition == Position.standing ) victim.CurrentPosition = Position.fighting; } // HORRIBLE HORRIBLE! We've got index numbers hard-coded. TODO: FIXME: BUG: Get rid of this! if( ch.IsNPC() && ch.MobileTemplate != null && ( ch.MobileTemplate.IndexNumber == 9316 || ch.MobileTemplate.IndexNumber == 9748 ) && MUDMath.NumberPercent() < 20 ) { CheckShout( ch, victim ); } ch.BreakInvisibility(); // Everyone gets at least one swing/breath in battle. // This handles breathing, roaring, etc. if (!CheckRaceSpecial(ch, victim, skill)) SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); // Thrikreen primary hand extra attack, only thri extra attack that is // given to non-warriors in addition to warriors if( ch.GetRace() == Race.RACE_THRIKREEN && MUDMath.NumberPercent() < ch.Level ) { if( ch.IsClass(CharClass.Names.warrior) ) { switch( MUDMath.NumberRange( 1, 4 ) ) { case 1: if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_one ) ) SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); break; case 2: if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two ) ) SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_two); break; case 3: if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) ) SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_three); break; case 4: if( Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) ) SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_four); break; } } else { SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); if( MUDMath.NumberPercent() < ch.Level / 2 ) { SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); } } } // Don't hurt a corpse. if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 ) { StopFighting( ch, false ); { return true; } } // For NPCs we assume they have max skill value for their level. // When checking combat skills we only prDescriptor.actice them on a successful // check in order to make them go up slower. If they go up too slow // we can always practice them before they check. chance = ch.GetAttackChance(2); if( MUDMath.NumberPercent() < chance ) { ch.PracticeSkill( "second attack" ); SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); if( ch.Fighting != victim ) { return false; } } // Check for Thri-Kreen arm #3 if( ch.GetRace() == Race.RACE_THRIKREEN && ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_three ) ) ) { if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) ) { if( ch.IsNPC() ) { if( !ch.HasSkill( "second attack" )) { chance = ch.Level / 5; // Up to 10% chance of third arm for psis and } // other miscellaneous thris else { chance = ((ch.Level - Skill.SkillList["second attack"].ClassAvailability[(int)ch.CharacterClass.ClassNumber]) * 2 + 25); } } else { if (((PC)ch).SkillAptitude.ContainsKey("second attack")) { chance = ((PC)ch).SkillAptitude["second attack"]; } else { chance = 0; } } if( chance > 95 ) chance = 95; if( MUDMath.NumberPercent() < chance ) { ch.PracticeSkill( "second attack" ); SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_three); if( ch.Fighting != victim ) { return false; } } } } chance = ch.GetAttackChance(3); if( MUDMath.NumberPercent() < chance ) { ch.PracticeSkill( "third attack" ); SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); if( ch.Fighting != victim ) { return false; } } chance = ch.GetAttackChance(4); if( MUDMath.NumberPercent() < chance ) { ch.PracticeSkill( "fourth attack" ); SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_one); if( ch.Fighting != victim ) { return false; } } // Check for dual wield. May want to allow a second swing when dual wielding. // We'll wait and see what combat looks like before we decide - Xangis wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_two ); if( wield ) { if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) ) { ch.PracticeSkill( "dual wield" ); if (ch.IsNPC()) { chance = ch.Level; } else { if (((PC)ch).SkillAptitude.ContainsKey("dual wield")) { chance = ((PC)ch).SkillAptitude["dual wield"] * 2 / 3; } else { chance = 0; } } chance += ch.IsClass(CharClass.Names.ranger) ? 10 : 0; if( MUDMath.NumberPercent() < chance ) { SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_two); } } if( ch.Fighting != victim ) { return false; } } // Check for fourth arm on thrikreen if( ch.GetRace() == Race.RACE_THRIKREEN && ( wield = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_four ) ) ) { if( wield.HasWearFlag( ObjTemplate.WEARABLE_WIELD ) ) { ch.PracticeSkill( "dual wield" ); chance = ch.IsNPC() ? ( ch.Level * 3 / 2 + 20 ) : ( (PC)ch ).SkillAptitude[ "dual wield" ]; if( chance > 95 ) { chance = 95; } if( MUDMath.NumberPercent() < chance ) { SingleAttack(ch, victim, skill, ObjTemplate.WearLocation.hand_four); } } if( ch.Fighting != victim ) { return false; } } // Don't hurt a corpse. if( victim.CurrentPosition == Position.dead || victim.Hitpoints < -10 ) { StopFighting( ch, false ); return true; } return false; }
/// <summary> /// Check tumble skill to see whether an attack is avoided. /// </summary> /// <param name="ch"></param> /// <returns></returns> public static bool CheckTumble( CharData ch ) { if (ch == null) return false; int chance; if( !ch.HasSkill( "tumble" ) ) return false; if( ch.IsNPC() ) chance = ch.Level / 2 + 8; else chance = ( (PC)ch ).SkillAptitude[ "tumble" ] / 3; chance += ch.GetCurrAgi() / 15; ch.PracticeSkill( "tumble" ); if( MUDMath.NumberPercent() >= chance ) return false; return true; }
/// <summary> /// Checks whether the victim is able to dodge the attacker's swing. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <returns></returns> public static bool CheckDodge( CharData ch, CharData victim ) { if( !victim.IsAwake() || victim.CurrentPosition < Position.reclining ) return false; if (ch.IsAffected(Affect.AFFECT_DAZZLE)) return false; if( !victim.HasSkill( "dodge" ) ) return false; int chance = victim.GetSkillChance("dodge"); // Size difference bonus for dodge for halflings - they get 2% dodge // bonus per size difference between them and the attacker. -- Xangis // Drow get a flat 15% bonus. if( victim.GetRace() == Race.RACE_HALFLING ) { if( ch.CurrentSize > victim.CurrentSize ) { chance += 3 * ( ch.CurrentSize - victim.CurrentSize ); } } else if( victim.HasInnate( Race.RACE_GOOD_DODGE ) ) { chance += 8; } else if( victim.HasInnate( Race.RACE_BAD_DODGE ) ) { chance -= 3; } // Bashed mobs/creatures have a hard time dodging if( victim.CurrentPosition < Position.fighting ) { chance -= 25; } // Leap is 16% max at level 50. Considering crappy thri hitpoints it's necessary. if( victim.GetRace() == Race.RACE_THRIKREEN && MUDMath.NumberPercent() <= ( victim.Level / 3 ) ) { SocketConnection.Act( "$N&n leaps over your attack.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "You leap over $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n leaps over $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); return true; } victim.PracticeSkill( "dodge" ); if( MUDMath.NumberPercent() >= chance - ch.Level ) return false; switch( MUDMath.NumberRange( 1, 2 ) ) { case 1: SocketConnection.Act( "$N&n dodges your attack.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "You dodge $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n dodges $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); break; case 2: SocketConnection.Act( "$N&n sidesteps your attack.", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "You narrowly dodge $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n avoids $n&n's attack.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); break; default: break; } if( ch.Fighting == null ) SetFighting( ch, victim ); if( victim.Fighting == null ) SetFighting( victim, ch ); return true; }
/// <summary> /// Player track command. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void TrackCommand(CharData ch, string[] str) { if( ch == null ) return; CharData victim; if (ch.IsAffected(Affect.AFFECT_TRACK)) { ch.SendText("You stop tracking.\r\n"); Combat.StopHunting(ch); ch.RemoveAffect(Affect.AFFECT_TRACK); return; } if (!ch.HasSkill("track")) { ch.SendText("You couldn't track an &+Lelephant&n in your own bedroom.\r\n"); return; } if (str.Length == 0) { ch.SendText("Whom are you trying to track?\r\n"); return; } if (ch.Riding) { ch.SendText("You can't sniff a trail mounted.\r\n"); return; } if (ch.FlightLevel != 0) { ch.SendText("You find tracks on the _ground_!\r\n"); return; } if (ch.InRoom.IsWater()) { ch.SendText("You can't track through water.\r\n"); return; } if (ch.CurrentPosition != Position.standing) { if (ch.CurrentPosition == Position.fighting) ch.SendText("You're too busy fighting .\r\n"); else ch.SendText("You must be standing to track!\r\n"); return; } /* only imps can hunt to different areas */ bool area = (ch.GetTrust() < Limits.LEVEL_OVERLORD); if (area) { victim = ch.GetCharInArea(str[0]); } else { victim = ch.GetCharWorld(str[0]); } if (!victim || (!victim.IsNPC() && (ch.IsRacewar(victim)) && !ch.IsImmortal())) { ch.SendText("You can't find a trail of anyone like that.\r\n"); return; } if (ch.InRoom == victim.InRoom) { SocketConnection.Act("You're already in $N&n's room!", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* * Deduct some movement. */ if (ch.CurrentMoves > 2) { ch.CurrentMoves -= 3; } else { ch.SendText("You're too exhausted to hunt anyone!\r\n"); return; } SocketConnection.Act("$n carefully sniffs the air.", ch, null, null, SocketConnection.MessageTarget.room); ch.WaitState(Skill.SkillList["track"].Delay); Exit.Direction direction = Track.FindPath(ch.InRoom.IndexNumber, victim.InRoom.IndexNumber, ch, -40000, area); if (direction == Exit.Direction.invalid) { SocketConnection.Act("You can't sense $N&n's trail from here.", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* * Give a random direction if the player misses the die roll. */ if ((ch.IsNPC() && MUDMath.NumberPercent() > 75) /* NPC @ 25% */ || (!ch.IsNPC() && MUDMath.NumberPercent() > /* PC @ norm */ ((PC)ch).SkillAptitude["track"])) { do { direction = Database.RandomDoor(); } while (!(ch.InRoom.ExitData[(int)direction]) || !(ch.InRoom.ExitData[(int)direction].TargetRoom)); } ch.PracticeSkill("track"); /* * Display the results of the search. */ ch.SetAffectBit(Affect.AFFECT_TRACK); string buf = String.Format("You sense $N&n's trail {0} from here...", direction.ToString()); SocketConnection.Act(buf, ch, null, victim, SocketConnection.MessageTarget.character); if (ch.CurrentPosition == Position.standing) { ch.Move(direction); } Combat.StartHunting(ch, victim); return; }
/// <summary> /// Command to add a spell to your spellbook. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Scribe(CharData ch, string[] str) { if( ch == null ) return; bool found = false; if (ch.IsNPC()) return; if (!ch.InRoom) { ch.SendText("You're not in a proper place for scribing.\r\n"); return; } CharData teacher = null; foreach (CharData iteacher in ch.InRoom.People) { if (!iteacher.IsNPC()) continue; if (iteacher.HasActionBit(MobTemplate.ACT_TEACHER)) { teacher = iteacher; break; } } if (teacher == null) { ch.SendText("Nobody here can teach you anything.\r\n"); return; } foreach (Object quill in ch.Carrying) { if (quill.ItemType == ObjTemplate.ObjectType.pen) { found = true; break; } } if (!found) { ch.SendText("You have nothing to write with!\r\n"); return; } if (str.Length == 0) { ch.SendText("Scribe what?\r\n"); return; } Spell spell = StringLookup.SpellLookup(String.Join(" ", str)); if (spell == null) { ch.SendText("No such spell.\r\n"); return; } if ((spell.SpellCircle[(int)teacher.CharacterClass.ClassNumber] * 4) > (teacher.Level + 3)) { ch.SendText("The teacher does not know that spell.\r\n"); return; } if (!spell.CanBeScribed) { ch.SendText("That spell is not common knowledge - You must quest for it.\r\n"); return; } if ((spell.SpellCircle[(int)ch.CharacterClass.ClassNumber] * 4) > (ch.Level + 3)) { ch.SendText("That spell is beyond you.\r\n"); return; } if (!((PC)ch).SpellAptitude.ContainsKey(spell.Name) || ((PC)ch).SpellAptitude[spell.Name] < 1) { // Scribe is used so rarely give them 5 chances to learn it... ch.PracticeSkill("Scribe"); ch.PracticeSkill("Scribe"); ch.PracticeSkill("Scribe"); ch.PracticeSkill("Scribe"); ch.PracticeSkill("Scribe"); string buf = String.Format("You scribe {0}.\r\n", spell.Name); ch.SendText(buf); ((PC)ch).SpellAptitude[spell.Name] = Limits.BASE_SPELL_ADEPT; int chance = 0; if (ch.HasSkill("scribe")) { chance = ((PC)ch).SkillAptitude["Scribe"]; } if (MUDMath.NumberPercent() < chance) ((PC)ch).SpellAptitude[spell.Name] += 5; if (MUDMath.NumberPercent() < chance) ((PC)ch).SpellAptitude[spell.Name] += 4; if (MUDMath.NumberPercent() < chance) ((PC)ch).SpellAptitude[spell.Name] += 3; if (MUDMath.NumberPercent() < chance) ((PC)ch).SpellAptitude[spell.Name] += 2; if (MUDMath.NumberPercent() < chance) ((PC)ch).SpellAptitude[spell.Name] += 1; ch.WaitState(Skill.SkillList["Scribe"].Delay); } else { ch.SendText("You already know that spell.\r\n"); } return; }
/// <summary> /// Attempt to trip a foe. Can initiate combat with this and can use during combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Trip(CharData ch, string[] str) { if( ch == null ) return; int chance; /* Check player's level and class, mobs can use this skill */ if ((!ch.HasSkill("trip"))) { ch.SendText("You would just fall over if you tried to trip someone.\r\n"); return; } if (ch.IsBlind()) { return; } CharData victim = ch.Fighting; if (str.Length != 0) { victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("You look around, unable to find them.\r\n"); return; } } else { if (!victim) { ch.SendText("You aren't fighting anyone.\r\n"); return; } } /* anti 'trip me' code */ if (victim == ch) { ch.SendText("You don't think you're clumsy enough already?\r\n"); return; } ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["trip"].Delay)); ch.PracticeSkill("trip"); if (ch.IsNPC()) { chance = (ch.Level * 3) / 2 + 10; } else { chance = ((PC)ch).SkillAptitude["trip"]; } if (chance > 90) { chance = 90; } if ((ch.Fighting == null) && (ch != victim)) { Combat.SetFighting(ch, victim); } if ((!victim.Fighting) && (victim != ch)) { Combat.SetFighting(victim, ch); } /* Mobs do NOT auto-trip! */ if (MUDMath.NumberPercent() < chance) { victim.WaitState((Skill.SkillList["trip"].Delay * 5 / 6)); SocketConnection.Act("You trip $N&n and send $M sprawling to the &n&+yearth&n!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n trips you and you go down!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n trips $N&n and $E falls face-first to the &n&+yground&n!", ch, null, victim, SocketConnection.MessageTarget.room_vict); if (victim.CurrentPosition > Position.reclining) { victim.CurrentPosition = Position.reclining; } } else { SocketConnection.Act("You try to trip $N&n and fall down!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n attempts to knock you from your feet, and falls down $sself!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n tries to trip $N&n and tumbles to the &n&+yground&n!", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.CurrentPosition = Position.reclining; } return; }
public static void ScribeScroll(CharData ch, string[] str) { if( ch == null ) return; Object scroll; Spell spell; if (String.IsNullOrEmpty(str[0])) { ch.SendText("Scribe what spell?\r\n"); return; } if (!(scroll = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one))) { ch.SendText("You hold nothing in your hand.\r\n"); return; } if (scroll.ItemType != ObjTemplate.ObjectType.scroll) { ch.SendText("You are not holding a &+Wparchment&n.\r\n"); return; } if ((spell = StringLookup.SpellLookup(str[0])) == null) { ch.SendText("You don't know any spells by that _name.\r\n"); return; } SocketConnection.Act("$n begins writing a &+Wscroll&n.", ch, scroll, null, SocketConnection.MessageTarget.room); ch.WaitState(Skill.SkillList["Scribe"].Delay); ch.PracticeSkill("Scribe"); if (!ch.IsNPC() && (MUDMath.NumberPercent() > ((PC)ch).SkillAptitude["brew"] || MUDMath.NumberPercent() > ((ch.GetCurrInt() - 13) * 5 + (ch.GetCurrWis() - 13) * 3))) { SocketConnection.Act("$p&n bursts in &n&+rflames&n!", ch, scroll, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n bursts in &+Rflames&n!", ch, scroll, null, SocketConnection.MessageTarget.room); scroll.RemoveFromWorld(); Combat.InflictDamage(ch, ch, ch.GetMaxHit(), "Scribe", ObjTemplate.WearLocation.none, AttackType.DamageType.fire); return; } scroll.Level = ch.Level * 2 / 3; scroll.Values[0] = ch.Level / 3; ch.ImprintSpell(spell, ch.Level, scroll); return; }
// This function needs to be rewritten to take args! public static void Whirlwind(CharData ch, string[] str) { if( ch == null ) return; bool found = false; if (!ch.IsNPC() && !ch.HasSkill("whirlwind")) { ch.SendText("You don't know how to do that...\r\n"); return; } Object wield = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!wield || wield.ItemType != ObjTemplate.ObjectType.weapon) { ch.SendText("You need to wield a weapon first.\r\n"); return; } SocketConnection.Act("$n&n holds $p&n firmly, and starts spinning round...", ch, wield, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You hold $p&n firmly, and start spinning round...", ch, wield, null, SocketConnection.MessageTarget.character); foreach (CharData roomChar in ch.InRoom.People) { if ((roomChar.IsNPC() || (ch.IsRacewar(roomChar) && !roomChar.IsImmortal())) && CharData.CanSee(roomChar, ch)) { found = true; SocketConnection.Act("$n&n turns towards YOU!", ch, null, roomChar, SocketConnection.MessageTarget.victim); Combat.SingleAttack(ch, roomChar, "whirlwind", ObjTemplate.WearLocation.hand_one); // Added small amount of lag per target hit ch.WaitState(3); } } if (!found) { SocketConnection.Act("$n&n looks dizzy, and a tiny bit embarrassed.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You feel dizzy, and a tiny bit embarrassed.", ch, null, null, SocketConnection.MessageTarget.character); } ch.WaitState(Skill.SkillList["whirlwind"].Delay); ch.PracticeSkill("whirlwind"); if (!found && MUDMath.NumberPercent() < 25) { SocketConnection.Act("$n&n loses $s balance and colapses into a heap.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You lose your balance and fall into a heap.", ch, null, null, SocketConnection.MessageTarget.character); ch.CurrentPosition = Position.stunned; } return; }
/// <summary> /// Command to use a magical staff. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Brandish(CharData ch, string[] str) { if( ch == null ) return; Object staff; if (!(staff = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one))) { ch.SendText("You hold nothing in your hand.\r\n"); return; } if (staff.ItemType != ObjTemplate.ObjectType.staff) { ch.SendText("You can brandish only with a &n&+ystaff&n.\r\n"); return; } if (ch.IsNPC() && !ch.IsFreewilled()) { SocketConnection.Act("You try to brandish $p&n, but you have no free will.", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n tries to brandish $p&n, but has no free will.", ch, staff, null, SocketConnection.MessageTarget.room); return; } String spellName = SpellNumberToTextMap.GetSpellNameFromNumber(staff.Values[3]); if (String.IsNullOrEmpty(spellName)) { ch.SendText("You try to zap, but your wand fizzles.\r\n"); Log.Error("Brandish: Spell number " + staff.Values[3] + " not found in SpellNumberToTextMap for object " + staff.ObjIndexNumber + "."); return; } Spell spell = StringLookup.SpellLookup(spellName); if (!spell) { ch.SendText("You try to zap, but your wand fizzles.\r\n"); Log.Error("Brandish: Spell '" + spellName + "' not found for object " + staff.ObjIndexNumber + ". Check that it exists in the spells file."); return; } ch.WaitState(2 * Event.TICK_COMBAT); if (staff.Values[2] > 0) { SocketConnection.Act("You brandish $p&n.", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n brandishes $p&n.", ch, staff, null, SocketConnection.MessageTarget.room); ch.PracticeSkill("staves"); if (!ch.IsNPC() && (MUDMath.NumberPercent() > ((PC)ch).SkillAptitude["staves"])) { switch (MUDMath.NumberBits(3)) { default: case 0: case 1: case 2: case 3: SocketConnection.Act("You are unable to invoke the power of $p&n.", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n is unable to invoke the power of $p&n.", ch, staff, null, SocketConnection.MessageTarget.room); return; case 4: case 5: case 6: SocketConnection.Act("You summon the power of $p&n, but it fizzles away.", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n summons the power of $p&n, but it fizzles away.", ch, staff, null, SocketConnection.MessageTarget.room); if (--staff.Values[2] <= 0) { SocketConnection.Act("$p&n blazes brightly and is gone.", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n blazes brightly and is gone.", ch, staff, null, SocketConnection.MessageTarget.room); staff.RemoveFromWorld(); ; } return; case 7: SocketConnection.Act("You can't control the power of $p&n, and it shatters!", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n shatters into tiny pieces!", ch, staff, null, SocketConnection.MessageTarget.room); staff.RemoveFromWorld(); Combat.InflictDamage(ch, ch, staff.Level, "staves", ObjTemplate.WearLocation.none, AttackType.DamageType.energy); return; } } } foreach (CharData roomChar in ch.InRoom.People) { if( ch == null ) return; switch (spell.ValidTargets) { default: Log.Error("Brandish: Bad TargetType for spell {0}.", spell.Name); return; case TargetType.none: if (roomChar != ch) continue; break; case TargetType.singleCharacterOffensive: if (ch.IsNPC() ? roomChar.IsNPC() : !roomChar.IsNPC()) continue; break; case TargetType.singleCharacterDefensive: if (ch.IsNPC() ? !roomChar.IsNPC() : roomChar.IsNPC()) continue; break; case TargetType.self: if (roomChar != ch) continue; break; } Magic.ObjectCastSpell(ch, spell, staff.Level, roomChar, null); } if (!ch.IsNPC() || (ch.IsNPC() && ch.IsAffected(Affect.AFFECT_CHARM))) { if (--staff.Values[2] <= 0) { SocketConnection.Act("$p&n blazes brightly and is gone.", ch, staff, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n blazes brightly and is gone.", ch, staff, null, SocketConnection.MessageTarget.room); staff.RemoveFromWorld(); } } return; }
/// <summary> /// Circle around behind someone and backstab them. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Circle(CharData ch, string[] str) { if( ch == null ) return; CharData victim; /* Verify that ch can circle. */ if (!ch.IsNPC() && !ch.HasSkill("circle")) { ch.SendText("You'd better leave the assassination trade to those more skilled.\r\n"); return; } /* No charmies or NPC's are allowed to circle. */ if (ch.IsNPC() && ch.IsAffected(Affect.AFFECT_CHARM)) { return; } /* Yeah, gallop around them without them noticing. */ if (ch.Riding) { ch.SendText("You can't circle while mounted.\r\n"); return; } /* Find the unlucky soul. */ if (str.Length == 0) { victim = ch.Fighting; } else { if (!(victim = ch.GetCharRoom(str[0]))) { ch.SendText("They aren't here.\r\n"); return; } } /* No target. */ if (!victim) { ch.SendText("Circle who?\r\n"); return; } /* Run around yourself? Ok. */ if (victim == ch) { ch.SendText("You spin around in a circle. Whee!\r\n"); return; } /* Check for protection of victim. */ victim = Combat.CheckGuarding(ch, victim); if (Combat.IsSafe(ch, victim)) { return; } // is_safe could wipe out victim, as it calls procs if a boss // check and see that victim is still valid if (!victim) { return; } /* Check if someone is attacking ch. */ CharData roomChar = null; foreach (CharData irch in ch.InRoom.People) { if (irch.Fighting == ch) { roomChar = irch; break; } } if (roomChar) { ch.SendText("You're too busy being hit right now.\r\n"); return; } Object obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!obj || obj.Values[3] != 11) { ch.SendText("You need to wield a piercing weapon.\r\n"); return; } SocketConnection.Act("You circle around behind $N&n...", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n circles around behind $N&n...", ch, null, victim, SocketConnection.MessageTarget.room_vict); Crime.CheckAttemptedMurder(ch, victim); ch.WaitState(Skill.SkillList["circle"].Delay); if (ch.IsNPC() || MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["circle"] + ch.GetCurrAgi() - victim.GetCurrAgi()) { /* Don't always switch. */ if (MUDMath.NumberPercent() < 40) { Combat.StopFighting(victim, false); } Combat.SingleAttack(ch, victim, "circle", ObjTemplate.WearLocation.hand_one); } else { SocketConnection.Act("You failed to get around $M!", ch, null, victim, SocketConnection.MessageTarget.character); } ch.PracticeSkill("circle"); return; }
public static void Brew(CharData ch, string[] str) { if( ch == null ) return; Object potion; Spell spell; if (str.Length == 0) { ch.SendText("Which spell do you want to brew into a &+Lpotion&n?\r\n"); return; } if (!(potion = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one))) { ch.SendText("You hold nothing in your hand.\r\n"); return; } if (potion.ItemType != ObjTemplate.ObjectType.potion) { ch.SendText("You are not holding a vial.\r\n"); return; } if ((spell = StringLookup.SpellLookup(str[0])) == null) { ch.SendText("You don't know any spells by that _name.\r\n"); return; } if (spell.ValidTargets != TargetType.singleCharacterDefensive && spell.ValidTargets != TargetType.self) { ch.SendText("You cannot brew that spell.\r\n"); return; } SocketConnection.Act("$n begins preparing a &+Lpotion&n.", ch, potion, null, SocketConnection.MessageTarget.room); ch.WaitState(Skill.SkillList["brew"].Delay); ch.PracticeSkill("brew"); if (!ch.IsNPC() && (MUDMath.NumberPercent() > ((PC)ch).SkillAptitude["brew"] || MUDMath.NumberPercent() > ((ch.GetCurrInt() - 13) * 5 + (ch.GetCurrWis() - 13) * 3))) { SocketConnection.Act("$p&n explodes violently!", ch, potion, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$p&n explodes violently!", ch, potion, null, SocketConnection.MessageTarget.room); potion.RemoveFromWorld(); Combat.InflictDamage(ch, ch, ch.GetMaxHit() / 16, "brew", ObjTemplate.WearLocation.none, AttackType.DamageType.energy); return; } potion.Level = ch.Level / 2; potion.Values[0] = ch.Level / 4; ch.ImprintSpell(spell, ch.Level, potion); return; }
/// <summary> /// Knock the weapon from an opponent's hand. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Disarm(CharData ch, string[] str) { if( ch == null ) return; int odds; /* Don't allow charmed mobiles to do this, check player's level */ if ((ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && !ch.HasSkill("disarm"))) { ch.SendText("You don't know how to disarm opponents.\r\n"); return; } if (!Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one) && !Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two)) { ch.SendText("You must wield a weapon to disarm.\r\n"); return; } if (!ch.Fighting) { ch.SendText("You aren't fighting anyone.\r\n"); return; } CharData victim = ch.Fighting; if (str.Length != 0) { if (!(victim = ch.GetCharRoom(str[0]))) { ch.SendText("They aren't here.\r\n"); return; } } if (victim.Fighting != ch && ch.Fighting != victim) { SocketConnection.Act("$E is not fighting you!", ch, null, victim, SocketConnection.MessageTarget.character); return; } if (!Object.GetEquipmentOnCharacter(victim, ObjTemplate.WearLocation.hand_one) && !Object.GetEquipmentOnCharacter(victim, ObjTemplate.WearLocation.hand_two)) { ch.SendText("Your opponent is not wielding a weapon.\r\n"); return; } if (victim.Level > ch.Level + 10) { ch.SendText("They are much too clever for such a clumsy attempt at that maneuver.\r\n"); return; } ch.WaitState(Skill.SkillList["disarm"].Delay); ch.PracticeSkill("disarm"); if (ch.IsNPC()) { odds = ch.Level; } else { odds = ((PC)ch).SkillAptitude["disarm"] / 2; } if (victim.IsNPC()) { odds += 2 * (ch.Level - victim.Level); } else { /* Offense skill helps prevent disarms */ odds -= ((PC)victim).SkillAptitude["offense"] / 4; } if (!Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one)) { odds /= 2; /* 1/2 as likely with only 2nd weapon */ } odds = Math.Min(odds, 98); odds = Math.Max(odds, 2); string lbuf = String.Format("Disarm: {0} attempting with {1}%% chance.", ch.Name, odds); ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); if (MUDMath.NumberPercent() < odds) { Combat.Disarm(ch, victim); } else if (MUDMath.NumberPercent() > 80) { ch.SendText("Expertly countering your maneuver, they dislodge your weapon and send it flying.\r\n"); Combat.Disarm(victim, ch); } else { ch.SendText("You failed in your attempt.\r\n"); } return; }
/// <summary> /// Move silently. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Sneak(CharData ch, string[] str) { if( ch == null ) return; /* Don't allow charmed mobs to do this, check player's skill */ if ((!ch.HasSkill("sneak"))) { ch.SendText("You're about as sneaky as a buffalo in tap shoes.\r\n"); return; } if (ch.Riding) { ch.SendText("You can't do that while mounted.\r\n"); return; } if (str.Length != 0 && !MUDString.StringsNotEqual(str[0], "off")) { if (!ch.IsAffected(Affect.AFFECT_SNEAK)) { ch.SendText("You're not sneaking.\r\n"); } else { ch.SendText("You stop sneaking around.\r\n"); ch.RemoveAffect(Affect.AFFECT_SNEAK); } return; } ch.SendText("You attempt to move silently.\r\n"); ch.RemoveAffect( Affect.AFFECT_SNEAK ); /* Check skill knowledge when moving only. */ Affect af = new Affect(Affect.AffectType.skill, "sneak", -1, Affect.Apply.none, 0, Affect.AFFECT_SNEAK); ch.AddAffect(af); ch.PracticeSkill("sneak"); ch.WaitState(10); return; }
/// <summary> /// A basic bandage self command, usable once per day. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void FirstAid(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC()) return; if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("You can't do that while fighting!\r\n"); return; } if (((PC)ch).FirstaidTimer > 0) { ch.SendText("You can only first aid once per day.\r\n"); return; } if (ch.Hitpoints < ch.GetMaxHit()) { ch.Hitpoints += MUDMath.Dice(3, (ch.Level / 2)) + 1; if (((PC)ch).SkillAptitude["bandage"] > 9) { ch.Hitpoints += ((PC)ch).SkillAptitude["bandage"] / 8; ch.PracticeSkill("bandage"); } if (ch.Hitpoints > ch.GetMaxHit()) { ch.Hitpoints = ch.GetMaxHit(); } } ((PC)ch).FirstaidTimer = 24; ch.SendText("You attempt to render first aid unto yourself.\r\n"); return; }
/// <summary> /// Springleap. Can be used to initiate combat and can be used during combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Springleap(CharData ch, string[] str) { if( ch == null ) return; int chance; /* Check player's level and class, mobs can use this skill */ if ((!ch.HasSkill("springleap"))) { ch.SendText("You'd better leave the martial arts to Bruce Lee.\r\n"); return; } if (ch.GetRace() == Race.RACE_CENTAUR) { ch.SendText("Your anatomy prevents you from springleaping.\r\n"); return; } if (ch.IsBlind()) { return; } CharData victim = ch.Fighting; if (str.Length != 0) { if (!(victim = ch.GetCharRoom(str[0])) || victim.CurrentPosition == Position.dead) { ch.SendText("You don't see them here.\r\n"); return; } } else { if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("You aren't fighting anyone.\r\n"); return; } } /* springleap self */ if (ch == victim) { ch.SendText("You can't quite figure out how to do that.\r\n"); return; } /* Check size of ch vs. victim. */ /* If ch is too small. */ if (ch.CurrentSize - 2 > victim.CurrentSize) { SocketConnection.Act("Your acrobatic maneuver cannot accurately leap into such a small being.", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* Ch 2 or more sizes larger than victim => bad! */ if (ch.CurrentSize + 2 < victim.CurrentSize) { SocketConnection.Act("Your acrobatic maneuver does not seem to work on someone so large.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n jumps into you, and slides down your leg.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n jumps into $N&n and slides down $S leg.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.WaitState(Skill.SkillList["springleap"].Delay); ch.CurrentPosition = Position.reclining; if (victim.Fighting == null) { Combat.SetFighting(victim, ch); } return; } ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["springleap"].Delay)); ch.PracticeSkill("springleap"); if (ch.IsNPC()) { chance = (ch.Level * 3) / 2 + 15; } else { chance = ((PC)ch).SkillAptitude["springleap"] - 5; } if (chance > 95) { chance = 95; } if (victim.CurrentPosition < Position.fighting) { chance /= 4; } if (MUDMath.NumberPercent() < chance) { ch.CurrentPosition = Position.fighting; SocketConnection.Act("&+WYour springleap knocks $N&n&+W on $S butt.&n", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("&+W$n&n&+W leaps gracefully at $N&n&+W, sending $M to the ground.&n", ch, null, victim, SocketConnection.MessageTarget.room); SocketConnection.Act("&+W$n&n&+W leaps at you, knocking you to the ground!&n", ch, null, victim, SocketConnection.MessageTarget.victim); if (victim.IsAffected(Affect.AFFECT_SINGING)) { victim.RemoveAffect(Affect.AFFECT_SINGING); SocketConnection.Act("$n&n gasps and falls silent as $e falls over backward!", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You abort your singing!\r\n"); } if (victim.IsAffected(Affect.AFFECT_CASTING)) { victim.RemoveAffect(Affect.AFFECT_CASTING); SocketConnection.Act("$n&n no longer has any idea what $e was casting.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("Lying on the ground, you realize you have no idea what you were just casting.\r\n"); } if (!ch.Fighting) { Combat.SetFighting(ch, victim); } if (!victim.Fighting) { Combat.SetFighting(victim, ch); } if (!Combat.CheckTumble(victim)) { victim.WaitState((Skill.SkillList["springleap"].Delay * 5 / 6)); if (victim.CurrentPosition > Position.sitting) { victim.CurrentPosition = Position.sitting; } Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "springleap", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } else { Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "springleap", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); ch.SendText("You roll with the blow, finally landing on your feet.\r\n"); SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", victim, null, null, SocketConnection.MessageTarget.room); } } else { bool pissedOff = false; if (ch.Fighting == victim || victim.GetCurrInt() > MUDMath.NumberPercent()) { pissedOff = true; } if (pissedOff) { SocketConnection.Act("As $N&n avoids your leap you crash to the ground.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n crashes to the ground as you avoid $s springleap.", ch, null, victim, SocketConnection.MessageTarget.victim); if (!ch.Fighting) { Combat.SetFighting(ch, victim); } if (!victim.Fighting) { Combat.SetFighting(victim, ch); } } else { SocketConnection.Act("You ungracefully leap at $N and miss, landing head first!", ch, null, victim, SocketConnection.MessageTarget.character); } SocketConnection.Act("$n&n misses a springleap and falls awkwardly to the ground.", ch, null, null, SocketConnection.MessageTarget.room); ch.CurrentPosition = Position.reclining; Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 4), "springleap", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } return; }
/// <summary> /// Bandage someone's wounds. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Bandage(CharData ch, string[] str) { if( ch == null ) return; if (ch.IsNPC() || !ch.HasSkill("bandage")) { ch.SendText("You don't know how to bandage!\r\n"); return; } if (str.Length == 0) { ch.SendText("Bandage whom?\r\n"); return; } CharData victim = ch.GetCharRoom(str[0]); if (victim == null) { ch.SendText("They're not here.\r\n"); return; } if (victim.Hitpoints > 0) { ch.SendText("They do not need your help.\r\n"); return; } int chance = ((PC)ch).SkillAptitude["bandage"]; if (ch.IsClass(CharClass.Names.cleric)) chance += 4; else if (ch.IsClass(CharClass.Names.antipaladin)) chance -= 4; /* Don't allow someone doing more than 1 pt. of damage with bandage. */ int change = (Math.Max(chance - MUDMath.NumberPercent(), -1) / 20) + 1; // Bandage is rarely used, make it likely to increase ch.PracticeSkill("bandage"); ch.PracticeSkill("bandage"); ch.PracticeSkill("bandage"); ch.WaitState(Skill.SkillList["bandage"].Delay); if (change < 0) { ch.SendText("You just made the problem worse!\r\n"); SocketConnection.Act("$n&n tries bandage you but your condition only worsens.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n tries bandage $N&n but $S condition only worsens.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else if (change > 0) { ch.SendText("You manage to fix them up a _bitvector.\r\n"); SocketConnection.Act("$n&n bandages you.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n bandages $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { ch.SendText("Your bandaging attempt had no effect.\r\n"); SocketConnection.Act("$n&n tries to bandage you but the wounds are too great.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n tries to bandage $N&n but is unable to have any effect.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } victim.Hitpoints += change; victim.UpdatePosition(); return; }
/// <summary> /// Steal an object or some coins from a victim. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Steal(CharData ch, string[] str) { if( ch == null ) return; Object obj = null; CharData victim; bool sleeping = false; string arg1 = String.Empty; string arg2 = String.Empty; string arg = String.Empty; int percent; if (!ch.HasSkill("steal") && !ch.IsAffected(Affect.AFFECT_CHARM)) { ch.SendText("Who are you trying to kid? You couldn't steal shoes from a &n&+mbl&+Mo&n&+ma&+Mte&n&+md&n corpse.\r\n"); return; } if (ch.Riding != null) { ch.SendText("You can't do that while mounted.\r\n"); return; } if (String.IsNullOrEmpty(arg1) || String.IsNullOrEmpty(arg2)) { ch.SendText("Steal what from whom?\r\n"); return; } if ((victim = ch.GetCharRoom(arg2)) == null) { ch.SendText("They aren't here.\r\n"); return; } if (victim == ch) { ch.SendText("That's pointless.\r\n"); return; } if (Combat.IsSafe(ch, victim)) return; if (!ch.IsImmortal()) { ch.WaitState(Skill.SkillList["steal"].Delay); } // Justice stuff Crime.CheckThief(ch, victim); if (ch.IsNPC()) { percent = ch.Level * 2; } else { percent = ((PC)ch).SkillAptitude["steal"]; } percent += ch.GetCurrLuck() / 20; /* Luck */ percent -= victim.Level; /* Character level vs victim's */ if (ch.GetRace() == Race.RACE_HALFLING) { // Halflings get a racial bonus percent += 10; } if (victim.IsAffected(Affect.AFFECT_CURSE)) percent += 15; if (ch.IsAffected(Affect.AFFECT_CURSE)) percent -= 15; if (!victim.IsAwake()) percent += 25; /* Sleeping characters are easier */ if (ch.CheckSneak()) percent += 10; /* Quiet characters steal better */ if (!CharData.CanSee(ch, victim)) percent += 10; /* Unseen characters steal better */ if (!MUDString.IsPrefixOf(arg1, "coins")) { percent = (int)(percent * 1.2); /* Cash is fairly easy to steal */ } else { int number = MUDString.NumberArgument(arg1, ref arg); int count = 0; foreach (Object iobj in victim.Carrying) { if (CharData.CanSeeObj(ch, iobj) && MUDString.NameContainedIn(arg, iobj.Name)) { if (++count == number) { obj = iobj; break; } } } if (!obj) { ch.SendText("You can't find it.\r\n"); return; } if (ch.Level < victim.Level) { // stealing from higher level is possible, but harder percent -= 5 * (victim.Level - ch.Level); } else { // slight bonus for mobs lower level percent += (ch.Level - victim.Level); } if (obj.WearLocation == ObjTemplate.WearLocation.none) /* Items worn are harder */ percent = (int)(percent * .8); else percent = (int)(percent * .4); } ch.PracticeSkill("steal"); if (percent > 85) percent = 85; if (percent < 2) percent = 2; if (percent < MUDMath.NumberPercent()) { /* * Failure. */ //strip sneak ch.RemoveAffect(Affect.AFFECT_SNEAK); // chance of removing invis if (ch.IsAffected(Affect.AFFECT_INVISIBLE) && MUDMath.NumberPercent() > percent) { ch.SendText("You really bungled that attempt.\r\n"); ch.RemoveAffect(Affect.AFFECT_INVISIBLE); } else { ch.SendText("Oops.\r\n"); } SocketConnection.Act("$n&n tried to steal from $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); if (victim.IsAwake()) { SocketConnection.Act("$n&n tried to steal from you!", ch, null, victim, SocketConnection.MessageTarget.victim); } else { sleeping = true; } // Thief flag for justice. // Added so blind mobs dont hit who ever failed steal from em. if (victim.IsNPC()) { if (!sleeping && !victim.IsBlind()) { CommandType.Interpret(victim, "kill " + ch.Name); } } else { if (!victim.IsBlind() && !sleeping && victim.IsAffected(Affect.AFFECT_BERZERK)) { victim.SendText("In your &+Rblood rage&n, you lash out in anger!\r\n"); CommandType.Interpret(victim, "kill " + ch.Name); } } /* if ( !Macros.IS_SET( ch.actflags, PC.PLAYER_THIEF ) ) { Macros.SET_BIT( ref ch.actflags, PC.PLAYER_THIEF ); buf = String.Format( "{0} became a THIEF by stealing from {1}", ch._name, victim._name ); Immtalk.Immtalk( ch, Immtalk.IMMTALK_CRIME, ch.GetTrust(), buf ); CharData.SavePlayer( ch ); } */ // } if (sleeping) { if (MUDMath.NumberPercent() < victim.GetCurrLuck()) { CommandType.Interpret(victim, "wake"); } } return; } //end failure if (!MUDString.IsPrefixOf(arg1, "coins")) { int amount = victim.GetGold() * MUDMath.NumberRange(1, 20) / 100; int amount2 = victim.GetSilver() * MUDMath.NumberRange(1, 20) / 100; int amount3 = victim.GetCopper() * MUDMath.NumberRange(1, 20) / 100; int amount4 = victim.GetPlatinum() * MUDMath.NumberRange(1, 20) / 100; if ((amount + amount2 + amount3 + amount4) <= 0) { ch.SendText("You couldn't get any &n&+wcoins&n.\r\n"); return; } ch.ReceiveGold(amount); ch.ReceiveSilver(amount2); ch.ReceiveCopper(amount3); ch.ReceivePlatinum(amount4); victim.SpendGold(amount); victim.SpendSilver(amount2); victim.SpendCopper(amount3); victim.SpendPlatinum(amount4); string text = String.Format("Success! You got {0} &+Wplatinum&n, {1} &+Ygold&n, {2} silver, and {3} &+ycopper&n.\r\n", amount2, amount3, amount, amount4); ch.SendText(text); return; } if (!ch.CanDropObject(obj) || obj.HasFlag(ObjTemplate.ITEM_INVENTORY)) { ch.SendText("You can't pry it away.\r\n"); return; } if (ch.CarryNumber + 1 > Limits.MAX_CARRY) { ch.SendText("You have your hands full.\r\n"); return; } if (ch.CarryWeight + obj.GetWeight() > ch.MaxCarryWeight()) { ch.SendText("You cannot carry that much weight.\r\n"); return; } if (obj.WearLocation != ObjTemplate.WearLocation.none) { ch.SendText("Very daring, and you got it!\r\n"); victim.UnequipObject(obj); } obj.RemoveFromChar(); obj.ObjToChar(ch); ch.SendText("Nice work.\r\n"); if (obj.Trap != null && obj.Trap.CheckTrigger( Trap.TriggerType.steal)) { ch.SetOffTrap(obj); if (ch.CurrentPosition == Position.dead) { return; } } return; }
/// <summary> /// Bash. Usable to initiate combat and during combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Bash(CharData ch, string[] str) { if( ch == null ) return; int chance; /* Check player's level and class, mobs can use this skill */ if ((!ch.HasSkill("bash"))) { ch.SendText("You'd better leave that to those with more skills.\r\n"); return; } if (ch.IsBlind() && !ch.Fighting) { return; } /* Verify a target. */ CharData victim = ch.Fighting; if (str.Length != 0) { victim = ch.GetCharRoom(str[0]); if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("They aren't anywhere to be found.\r\n"); return; } } else { if (!victim || victim.CurrentPosition == Position.dead) { ch.SendText("You aren't fighting anyone.\r\n"); return; } } /* Bash self? Ok! */ // Toned down the damage cuz you can't really bash yourself // like you could with someone else. if (victim == ch) { ch.SendText("You throw yourself to the ground!\r\n"); SocketConnection.Act("$N&n knocks $mself to the ground.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.CurrentPosition = Position.kneeling; ch.WaitState((Skill.SkillList["bash"].Delay * 8) / 10); Combat.InflictDamage(ch, ch, MUDMath.NumberRange(1, 3), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); return; } /* Check size of ch vs. victim. */ /* If ch is too small. */ if (ch.CurrentSize < victim.CurrentSize) { SocketConnection.Act("$N&n is too big for you to bash!", ch, null, victim, SocketConnection.MessageTarget.character); return; } /* Ch 2 or more sizes larger than victim => bad! */ if (ch.CurrentSize - 2 > victim.CurrentSize) { SocketConnection.Act("You nearly topple over as you try to bash $N&n.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n nearly topples over as $e attempts to bash you.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n nearly topples over as $e attempts to bash $N&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.WaitState((Skill.SkillList["bash"].Delay)); ch.CurrentPosition = Position.kneeling; if (victim.Fighting == null) { Combat.SetFighting(victim, ch); } return; } /* Lag to basher from bash. Pets get more lag because pets are cheesy */ if (!ch.IsNPC()) { ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["bash"].Delay)); } else { ch.WaitState((Skill.SkillList["bash"].Delay * 6 / 5)); } /* Base chance to bash, followed by chance modifications. */ if (ch.IsNPC()) { chance = (ch.Level * 3) / 2 + 15; } else { chance = ((PC)ch).SkillAptitude["bash"] - 5; } if (victim.CurrentPosition < Position.fighting) { chance /= 5; //used to be 0 } else { chance += ch.GetCurrAgi() - victim.GetCurrAgi(); } if (chance > 95) { chance = 95; } Object obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!obj) { /* No primary item. */ if (!(obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two))) { /* No items in hand. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("You lower your shoulder and attempt to bash without a shield...\r\n"); } else { chance -= 3; // Hidden penalty for not having a shield } } else if (obj.ItemType != ObjTemplate.ObjectType.shield) { /* Secondary item isn't a shield, no primary. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("Bashing without a shield is tough, but you try anyway...\r\n"); } else { chance -= 5; // Small hidden penalty for not having a shield } } /* Secondary item is a shield, no primary. */ else if (ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin)) { chance += 3; // Small hidden bonus for having a shield } } else if (obj.ItemType != ObjTemplate.ObjectType.shield) { /* Primary item isn't a shield. */ if (!(obj = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two))) { /* No secondary. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("Without a shield, bashing is a wistful thought, but you try anyway...\r\n"); } else { chance -= 5; // Hidden penalty for not having a shield } } else if (obj.ItemType != ObjTemplate.ObjectType.shield) { /* Secondary item is not a shield. */ if (!ch.IsClass(CharClass.Names.paladin) && !ch.IsClass(CharClass.Names.antipaladin)) { if (!ch.IsClass(CharClass.Names.warrior)) { chance -= 25; } else { chance -= 20; } ch.SendText("Without a shield, your shoulder bash is but wishful thinking...\r\n"); } else { chance -= 5; // Hidden penalty for not having a shield } } else if (ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin)) { /* Secondary is a shield. */ chance += 3; // Small hidden bonus for having a shield } else if (ch.IsClass(CharClass.Names.ranger)) { chance -= 8; } else if (ch.IsClass(CharClass.Names.warrior)) { chance -= 5; } } // Centaurs are awful damned hard to bash -- Xangis if (victim.GetRace() == Race.RACE_CENTAUR) { chance -= 25; } // damned high penalty for bashing blind if (ch.IsAffected(Affect.AFFECT_BLIND) && !victim.IsAffected(Affect.AFFECT_BLIND)) { chance /= 10; } if (ch.IsAffected(Affect.AFFECT_BLIND) && victim.IsAffected(Affect.AFFECT_BLIND)) { chance /= 4; } ch.PracticeSkill("bash"); /* Start a fight if not already in one. */ if (ch != victim) { if (!ch.Fighting) { Combat.SetFighting(ch, victim); } if (!victim.Fighting) { Combat.SetFighting(victim, ch); } } string lbuf = "Bash: " + ch.Name + " bashing " + victim.Name + " with " + chance + " chance."; ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_SPAM, 0, lbuf); /* Do the bash, deal the damage. */ if (MUDMath.NumberPercent() < chance) { /* Hit the bash. */ if (victim.IsAffected(Affect.AFFECT_SINGING)) { victim.RemoveAffect(Affect.AFFECT_SINGING); SocketConnection.Act("$n&n chokes on a note and falls silent as $e slams into the ground!", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("You abort your singing!\r\n"); } if (victim.IsAffected(Affect.AFFECT_CASTING)) { victim.RemoveAffect(Affect.AFFECT_CASTING); SocketConnection.Act("$n&n's eyes roll back in $s head and $e forgets all about $s spell.", victim, null, null, SocketConnection.MessageTarget.room); victim.SendText("Being knocked over so forcefully makes it hard to cast.\r\n"); } if (!Combat.CheckTumble(victim)) { victim.WaitState(((Skill.SkillList["bash"].Delay * 5) / 6)); if (victim.CurrentPosition > Position.kneeling) { victim.CurrentPosition = Position.kneeling; } victim.SendText("You are knocked to the ground!\r\n"); Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, ch.Level), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); } else { Combat.InflictDamage(ch, victim, MUDMath.NumberRange(1, (ch.Level / 3)), "bash", ObjTemplate.WearLocation.none, AttackType.DamageType.bludgeon); victim.SendText("You roll with the blow, finally landing on your feet.\r\n"); SocketConnection.Act("$n&n rolls with the blow, finally landing on $s feet.", victim, null, null, SocketConnection.MessageTarget.room); } } else { /* Miss the bash. */ SocketConnection.Act("As $N&n avoids your bash, you topple to the &n&+yground&n with a loud crash.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n crashes to the &n&+yground&n as you sidestep $s bash.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n misses $s bash at $N&n and is driven to the &n&+yground&n.", ch, null, victim, SocketConnection.MessageTarget.room_vict); ch.CurrentPosition = Position.kneeling; } return; }
/// <summary> /// Checks whether the victim is able to riposte the attacker's swing. Returns false /// if failed, true if successful. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <returns></returns> static bool CheckRiposte( CharData ch, CharData victim ) { if( !victim.IsAwake() || victim.CurrentPosition < Position.reclining ) return false; if( ch.IsAffected( Affect.AFFECT_DAZZLE ) ) return false; if( ch.IsAffected( Affect.AFFECT_BLIND ) ) return false; if( ch.IsAffected(Affect.AFFECT_CASTING ) ) return false; if( !victim.HasSkill( "riposte" ) ) return false; int chance = ch.GetSkillChance("riposte"); if (victim.IsNPC()) { // Mobs more often than not don't have weapons // so they should get bonuses for actually // having them if( Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_one ) ) { chance += 3; } } else { if( !Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_one ) ) { // Have to have a weapon to riposte. If only holding secondary weapon chances are lowered. if( !Object.GetEquipmentOnCharacter( victim, ObjTemplate.WearLocation.hand_two )) { return false; } chance /= 2; } victim.PracticeSkill( "riposte" ); } if( MUDMath.NumberPercent() >= (( chance - ch.Level ) / 3 ) ) return false; switch( MUDMath.NumberRange(1,3)) { case 1: SocketConnection.Act( "$N&n deflects your blow and strikes back at YOU!", ch, null, victim, SocketConnection.MessageTarget.character ); SocketConnection.Act( "You deflect $n&n's attack and strike back at $m.", ch, null, victim, SocketConnection.MessageTarget.victim ); SocketConnection.Act( "$N&n deflects $n&n's attack and strikes back at $m.", ch, null, victim, SocketConnection.MessageTarget.room_vict ); break; case 2: SocketConnection.Act("$N&n knocks your swing aside and strikes back at YOU!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("You knock $n&n's attack aside and strikes back at $m.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$N&n knocks $n&n's attack aside and strikes back at $m.", ch, null, victim, SocketConnection.MessageTarget.room_vict); break; case 3: SocketConnection.Act("$N&n blocks your strike and swings back at YOU!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("You block $n&n's strike aside and swing back at $m.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$N&n block $n&n's strike and swings back at $m.", ch, null, victim, SocketConnection.MessageTarget.room_vict); break; } return true; }