// This _function should prevent a mob from spamming // spellups on itself if it is already affected by the spell. // in the Spellup() _function, checks for Affect.AFFECT_WHATEVER // still need to be done. - Xangis static bool CheckSpellup( CharData ch, string name, int percent ) { if (ch == null) return false; if (String.IsNullOrEmpty(name)) return false; Spell spell = Spell.SpellList[name]; if (spell == null) { return false; } // Keep mobs from casting spells they are affected by if( ch.HasAffect( Affect.AffectType.spell, spell ) ) return false; if( ( ch.HasSpell( name ) ) && ( MUDMath.NumberPercent() < percent ) ) { if (spell.ValidTargets != TargetType.singleCharacterDefensive && spell.ValidTargets != TargetType.self) Log.Error( "CheckSpellup: Mob casting spell {0} which is neither TargetType.self nor TargetType.defensive.", spell ); SocketConnection.Act( "$n&n starts casting...", ch, null, null, SocketConnection.MessageTarget.room ); ch.SetAffectBit( Affect.AFFECT_CASTING ); CastData caster = new CastData(); caster.Who = ch; caster.Eventdata = Event.CreateEvent(Event.EventType.spell_cast, spell.CastingTime, ch, ch, spell); Database.CastList.Add( caster ); return true; } return false; }
/// <summary> /// Tracking mob has found the person its after. Attack or react accordingly. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void FoundPrey( CharData ch, CharData victim ) { string victname = String.Empty; string text = String.Empty; string lbuf = String.Empty; if (!victim) { Log.Error("FoundPrey: null victim", 0); return; } if (!victim.InRoom) { Log.Error("FoundPrey: null victim._inRoom", 0); return; } ImmortalChat.SendImmortalChat(null, ImmortalChat.IMMTALK_HUNTING, 0, string.Format("{0}&n has found {1}.", ch.ShortDescription, victim.Name)); if (ch.IsAffected(Affect.AFFECT_TRACK)) { ch.RemoveAffect(Affect.AFFECT_TRACK); Combat.StopHunting(ch); return; } if (ch.IsAffected(Affect.AFFECT_JUSTICE_TRACKER)) { /* Give Justice the ability to ground flying culprits */ if (victim.FlightLevel != 0) { SocketConnection.Act("$n&n forces you to land!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n forces $N&n to land!", ch, null, victim, SocketConnection.MessageTarget.room_vict); victim.FlightLevel = 0; } SocketConnection.Act("$n&n says, 'Stop, $N&n, you're under ARREST!'", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n says, 'Stop, $N&n, you're under ARREST!'", ch, null, victim, SocketConnection.MessageTarget.room); SocketConnection.Act("$n&n chains you up.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n binds $N&n so $E can't move.", ch, null, victim, SocketConnection.MessageTarget.room); victim.SetAffectBit(Affect.AFFECT_BOUND); victim.RemoveFromRoom(); if (ch.InRoom.Area.JailRoom != 0) { victim.AddToRoom(Room.GetRoom(victim.InRoom.Area.JailRoom)); } else { victim.SendText("Justice is broken in this town - there is no jail and you're screwed.\r\n"); } Combat.StopHunting(ch); return; } victname = victim.IsNPC() ? victim.ShortDescription : victim.Name; if (ch.FlightLevel != victim.FlightLevel) { if (ch.CanFly()) { if (ch.FlightLevel < victim.FlightLevel && ch.FlightLevel < CharData.FlyLevel.high) { Command.Fly(ch, new string[] { "up" }); } else { Command.Fly(ch, new string[] { "down" }); } } else { SocketConnection.Act("$n peers around looking for something.", ch, null, null, SocketConnection.MessageTarget.room); } return; } if (!CharData.CanSee(ch, victim)) { if (MUDMath.NumberPercent() < 90) return; switch (MUDMath.NumberBits(5)) { case 0: text = String.Format("You can't hide forever, {0}!", victname); Command.Say(ch, new string[]{text}); break; case 1: SocketConnection.Act("$n&n sniffs around the room.", ch, null, victim, SocketConnection.MessageTarget.room); text = "I can smell your blood!"; Command.Say(ch, new string[]{text}); break; case 2: text = String.Format("I'm going to tear {0} apart!", victname); Command.Yell(ch, new string[]{text}); break; case 3: Command.Say(ch, new string[]{"Just wait until I find you..."}); break; default: SocketConnection.Act("$p peers about looking for something.", ch, null, null, SocketConnection.MessageTarget.room); break; } return; } if (ch.InRoom.HasFlag(RoomTemplate.ROOM_SAFE) && ch.IsNPC()) { text = String.Format("Hunting mob {0} found a safe room {1}.", ch.MobileTemplate.IndexNumber, ch.InRoom.IndexNumber); Log.Trace(text); return; } if (ch.CurrentPosition > Position.kneeling) { switch (MUDMath.NumberBits(5)) { case 0: text = String.Format("I will eat your heart, {0}!", victname); Command.Say(ch, new string[]{text}); break; case 1: text = String.Format("You want a piece of me, {0}?", victname); Command.Say(ch, new string[]{text}); break; case 2: text = String.Format("How does your flesh taste {0}, like chicken?", victname); Command.Say(ch, new string[]{text}); break; case 3: SocketConnection.Act("$n&n howls gleefully and lunges at $N&n!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n howls gleefully and lunges at you!", ch, null, victim, SocketConnection.MessageTarget.victim); break; case 4: SocketConnection.Act("$n&n charges headlong into $N&n!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); SocketConnection.Act("$n&n charges headlong into you!", ch, null, victim, SocketConnection.MessageTarget.victim); break; default: break; } Combat.StopHunting(ch); Combat.CheckAggressive(victim, ch); if (ch.Fighting) return; // Backstab if able, otherwise just kill them. // Kill if they don't have the skill or if they don't have a stabber. if (!ch.HasSkill("backstab")) { Combat.CombatRound(ch, victim, String.Empty); } else if (!Combat.Backstab(ch, victim)) { Combat.CombatRound(ch, victim, String.Empty); } } return; }
/// <summary> /// Check for use of Direct targeted spells (TargetType.singleCharacterOffensive) /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> /// <param name="spell"></param> /// <param name="percent"></param> /// <returns></returns> public static bool CheckOffensive( CharData ch, CharData victim, Spell spell, int percent ) { if (ch == null) return false; string buf = String.Format("CheckOffensive: spell ({0})'{1}'", spell, spell.Name); Log.Trace( buf ); if( spell == null ) return false; if( ch.HasSpell(spell) && ( MUDMath.NumberPercent() < percent ) ) { if (spell.ValidTargets != TargetType.singleCharacterOffensive && spell.ValidTargets != TargetType.none && spell.ValidTargets != TargetType.singleCharacterRanged) Log.Error( "Check_spellup: Mob casting spell {0} which is neither _targetType offensive nor ignore.a", spell ); SocketConnection.Act( "$n&n starts casting...", ch, null, null, SocketConnection.MessageTarget.room ); ch.SetAffectBit( Affect.AFFECT_CASTING ); CastData caster = new CastData(); caster.Who = ch; caster.Eventdata = Event.CreateEvent(Event.EventType.spell_cast, spell.CastingTime, ch, victim, spell); Database.CastList.Add( caster ); return true; } return false; }
/// <summary> /// Flee: Attempt to run away from combat. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Flee(CharData ch, string[] str) { if( ch == null ) return; int attempt; int chances; if (ch.CurrentPosition < Position.reclining || ch.Wait > 0) { return; } // Remove memorization and meditation bits - Xangis if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEDITATING)) { SocketConnection.Act("$N&n is disrupted from meditation.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("Your meditation is disrupted.", ch, null, null, SocketConnection.MessageTarget.character); ch.RemoveActionBit(PC.PLAYER_MEDITATING); } if (!ch.IsNPC() && ch.HasActionBit(PC.PLAYER_MEMORIZING)) { SocketConnection.Act("$N&n abandons $S studies.", ch, null, null, SocketConnection.MessageTarget.room); SocketConnection.Act("You abandon your studies.", ch, null, null, SocketConnection.MessageTarget.character); ch.RemoveActionBit(PC.PLAYER_MEMORIZING); } if (ch.CurrentPosition < Position.fighting) { ch.SendText("You scramble madly to your feet!\r\n"); SocketConnection.Act("$n&n scrambles madly to $s feet!", ch, null, null, SocketConnection.MessageTarget.room); ch.CurrentPosition = Position.standing; return; } if (!ch.InRoom) { ch.SendText("You give up when you realize there's nowhere to flee to.\r\n"); } // Panicked people can flee when not fighting. CharData victim = ch.Fighting; if (!victim) { if (ch.CurrentPosition == Position.fighting) { ch.CurrentPosition = Position.standing; } } if (ch.IsAffected(Affect.AFFECT_BERZERK)) { ch.SendText("You can't flee, you're in a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!\r\n"); return; } if (ch.IsAffected( Affect.AFFECT_BOUND)) { ch.SendText("You are bound! You can't move!\r\n"); SocketConnection.Act("$n&n tries to flee, but is tied up!", ch, null, null, SocketConnection.MessageTarget.room); return; } if (ch.IsAffected( Affect.AFFECT_HOLD) || ch.IsAffected( Affect.AFFECT_MINOR_PARA)) { ch.SendText("You can't move!\r\n"); SocketConnection.Act("$n&n tries to flee, but $e can't move!", ch, null, null, SocketConnection.MessageTarget.room); return; } // You should almost always be able to flee when not fighting. if (ch.CurrentPosition == Position.standing) { chances = 30; } else { chances = 6; } Room wasIn = ch.InRoom; for (attempt = 0; attempt < chances; attempt++) { Exit exit; Exit.Direction door = Database.RandomDoor(); if ((exit = wasIn.GetExit(door)) == null || !exit.TargetRoom || exit.TargetRoom == wasIn || exit.HasFlag(Exit.ExitFlag.closed) || (ch.IsNPC() && (Room.GetRoom(exit.IndexNumber).HasFlag(RoomTemplate.ROOM_NO_MOB) || (ch.HasActionBit(MobTemplate.ACT_STAY_AREA) && exit.TargetRoom.Area != ch.InRoom.Area)))) { continue; } if (ch.Riding && ch.Riding.Fighting) { Combat.StopFighting(ch.Riding, true); } // Just to keep the damned messages from being wacky... ch.SetAffectBit(Affect.AFFECT_IS_FLEEING); ch.Move(door); ch.RemoveAffect(Affect.AFFECT_IS_FLEEING); if (ch.InRoom == wasIn) { break; } Room nowIn = ch.InRoom; ch.InRoom = wasIn; SocketConnection.Act("$n&n panics and attempts to flee...", ch, null, null, SocketConnection.MessageTarget.room, true); string text; if (ch.CheckSneak()) { SocketConnection.Act("$n&n has fled!", ch, null, null, SocketConnection.MessageTarget.room); } else { text = String.Format("$n&n flees {0}ward.", door.ToString()); SocketConnection.Act(text, ch, null, null, SocketConnection.MessageTarget.room, true); } ch.InRoom = nowIn; text = String.Format("You flee {0}ward!\r\n", door.ToString()); ch.SendText(text); Combat.StopFighting(ch, true); return; } SocketConnection.Act("$n&n tries to flee but can't make it out of here!", ch, null, null, SocketConnection.MessageTarget.room, true); ch.SendText("&+WYour escape is blocked!\r\n"); return; }
/// <summary> /// Hide yourself or an object. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Hide(CharData ch, string[] str) { if( ch == null ) return; /* Check player's skill */ if (!ch.HasSkill("hide")) { if(str.Length != 0) { HideItem(ch, new[] { str[0] }); return; } ch.SendText("You're far too obvious to hide anywhere.\r\n"); return; } if (ch.Riding) { ch.SendText("You can't do that while mounted.\r\n"); return; } if (ch.CurrentPosition <= Position.sleeping) { return; } ch.SendText("You attempt to hide.\r\n"); if (ch.IsAffected(Affect.AFFECT_HIDE)) { ch.RemoveAffect(Affect.AFFECT_HIDE); } if (ch.CheckSkill("hide")) { ch.SetAffectBit(Affect.AFFECT_HIDE); } ch.WaitState(12); return; }
/// <summary> /// Command to climb something. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Climb(CharData ch, string[] str) { if( ch == null ) return; int chance; if (!ch.HasSkill("climb")) { ch.SendText("You lack the skills to climb anything.\r\n"); return; } if (str.Length == 0) { ch.SendText("Climb what?\r\n"); return; } Object obj = ch.GetObjHere(str[0]); if (!obj) { ch.SendText("Uhh... what exactly did you want to climb!?\r\n"); return; } if (obj.ItemType != ObjTemplate.ObjectType.wall) { ch.SendText("That wasn't exactly designed for climbing.\r\n"); return; } if (ch.IsNPC()) { chance = ch.Level * 3 / 2 + 20; } else { chance = ((PC)ch).SkillAptitude["climb"]; } // Agility helps. chance += ch.GetCurrAgi() / 10; switch (obj.ObjIndexData.IndexNumber) { case StaticObjects.OBJECT_NUMBER_WALL_STONE: chance += 5; break; case StaticObjects.OBJECT_NUMBER_WALL_IRON: chance -= 15; break; default: ch.SendText("That wasn't exactly designed for climbing.\r\n"); return; } // Maximum chance of 98% if (chance > 98) { chance = 98; } if (MUDMath.NumberPercent() >= chance) { ch.SendText("You try to climb it, but you fall on your ass!\r\n"); ch.CurrentPosition = Position.sitting; ch.WaitState(5); return; } ch.SendText("With great skill, you scale the wall!\r\n"); // Value 0 of a wall object is the direction that has been walled... // This means that they should move in that direction. We leave it up to // move_char to make sure that there is actually an exit in that direction. // we use the climbing bit to allow them to pass the walls in move_char. ch.SetAffectBit(Affect.AFFECT_CLIMBING); ch.Move((Exit.Direction)obj.Values[0]); ch.RemoveAffect(Affect.AFFECT_CLIMBING); return; }
public static void Chameleon(CharData ch, string[] str) { if( ch == null ) return; if (!ch.IsNPC() && !ch.HasSkill("chameleon power")) { ch.SendText("You don't know how to act like a chameleon.\r\n"); return; } ch.SendText("You attempt to blend in with your surroundings.\r\n"); if (ch.IsAffected(Affect.AFFECT_HIDE)) { ch.RemoveAffect(Affect.AFFECT_HIDE); } if (ch.CheckSkill("chameleon power")) { ch.SetAffectBit(Affect.AFFECT_HIDE); } return; }
/// <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> /// Invoke a magic item. /// </summary> /// <param name="ch"></param> /// <param name="obj"></param> public static void Invoke(CharData ch, Object obj) { if (obj.HasAffect(Affect.AFFECT_STONESKIN) && !ch.IsAffected(Affect.AFFECT_STONESKIN)) { Spell spl = Spell.SpellList["stoneskin"]; if (spl != null) { spl.Invoke(ch, Math.Max(obj._level, ch.Level), ch); } } if (obj.HasAffect(Affect.AFFECT_FLYING) && !ch.IsAffected(Affect.AFFECT_FLYING)) { ch.SetAffectBit(Affect.AFFECT_FLYING); ch.SendText("Your feet rise off the ground.\r\n"); SocketConnection.Act("$n's feet rise off the ground.", ch, null, null, SocketConnection.MessageTarget.room); } return; }
/// <summary> /// Called by the cast function to process a spell's targets and react accordingly. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="argument"></param> private static void ProcessSpellTargets(CharData ch, Spell spell, string argument) { Object obj = null; Target target = null; CharData victim = null; if (!ch.IsClass(CharClass.Names.bard)) switch (spell.ValidTargets) { default: Log.Error("Magic.Cast: bad target type for spell {0}. Type is: {1}", spell.Name, spell.ValidTargets.ToString()); return; case TargetType.none: target = new Target(argument); break; case TargetType.singleCharacterWorld: victim = ch.GetCharWorld(argument); if (victim == null) { ch.SendText("Cast the spell on whom?\r\n"); return; } target = new Target(victim); break; case TargetType.trap: ch.SendText("You cannot cast a trap!\r\n"); return; case TargetType.singleCharacterOffensive: if (String.IsNullOrEmpty(argument)) { victim = ch.Fighting; if (victim == null) { if (ch.IsClass(CharClass.Names.psionicist)) ch.SendText("Will the spell upon whom?\r\n"); else ch.SendText("Cast the spell upon whom?\r\n"); return; } } else { victim = ch.GetCharRoom(argument); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } } if (ch.IsAffected( Affect.AFFECT_CHARM) && ch.Master == victim) { ch.SendText("You can't do that to your master!.\r\n"); return; } if (Combat.IsSafe(ch, victim)) return; // Combat.IsSafe could wipe out victim, as it calls procs if a boss // check and see that victim is still valid if (!victim) return; Crime.CheckAttemptedMurder(ch, victim); target = new Target(victim); ch.BreakInvisibility(); break; case TargetType.singleCharacterDefensive: if (String.IsNullOrEmpty(argument)) { victim = ch; } else { victim = ch.GetCharRoom(argument); if (victim == null) { ch.SendText("They aren't here.\r\n"); return; } } target = new Target(victim); break; case TargetType.self: if (!String.IsNullOrEmpty(argument) && !MUDString.NameContainedIn(argument, ch.Name) && "me".Equals(argument, StringComparison.CurrentCultureIgnoreCase) && "self".Equals(argument, StringComparison.CurrentCultureIgnoreCase)) { ch.SendText("You cannot cast this spell on another.\r\n"); return; } target = new Target(ch); break; case TargetType.objectInInventory: if (String.IsNullOrEmpty(argument)) { ch.SendText("What item should the spell be cast upon?\r\n"); return; } obj = ch.GetObjCarrying(argument); if (obj == null) { ch.SendText("You are not carrying that.\r\n"); return; } target = new Target(obj); break; case TargetType.objectInRoom: if (String.IsNullOrEmpty(argument)) { ch.SendText("What should the spell be cast upon?\r\n"); return; } obj = ch.GetObjHere(argument); if (obj == null) { ch.SendText("You do not see that here.\r\n"); return; } target = new Target(obj); break; case TargetType.objectCorpse: target = new Target(argument); break; case TargetType.objectOrCharacter: if (String.IsNullOrEmpty(argument)) { if (ch.Fighting != null) victim = ch.Fighting; else { ch.SendText("Cast upon what?\r\n"); return; } } else if (!(victim = ch.GetCharRoom(argument))) { obj = ch.GetObjHere(argument); } if (victim != null) { target = new Target(victim); } else if (obj != null) { target = new Target(obj); } else { ch.SendText("You do not see that here.\r\n"); return; } break; case TargetType.singleCharacterRanged: if (String.IsNullOrEmpty(argument)) { victim = ch.Fighting; if (victim == null) { ch.SendText("Cast the spell on whom?\r\n"); return; } } else { victim = ch.GetCharRoom(argument); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } // Ranged combat. // // TODO: FIXME: The next line does not successfully get the required argument. //int dir = Movement.FindExit(ch, arg3); //if (ch._level >= Limits.LEVEL_IMMORTAL) //{ // buf = String.Format("Looking for {0} to the {1}.\r\n", arg2, arg3); // ch.SendText(buf); //} //if (ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.walled) // || ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.blocked) // || ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.secret) // || ch._inRoom._exitData[dir].HasFlag(Exit.ExitFlags.closed) // || !ch._inRoom._exitData[dir]._targetRoom // || ch._inRoom._area != ch._inRoom._exitData[dir]._targetRoom._area) //{ // ch.SendText("You see nothing in that direction.\r\n"); // return; //} //room2 = Movement.FindRoom(ch, arg3); //if (room2 == null) //{ // ch.SendText("You see nothing in that direction.\r\n"); // return; //} //victim = CharData.GetCharAtRoom(room2, ch, arg2); //if (victim == null) //{ // Room room3; // if (room2._exitData[dir] && ((room3 = Room.GetRoom(room2._exitData[dir]._vnum))) && // spell == Spell.SpellList["fireball"]) // { // victim = CharData.GetCharAtRoom(room3, ch, arg2); // } //} //if (victim == null) //{ // ch.SendText("They aren't here.\r\n"); // return; //} //} //end else } //end else if (ch.IsAffected(Affect.AFFECT_CHARM) && ch.Master == victim) { ch.SendText("You can't do that to your master!.\r\n"); return; } if (Combat.IsSafe(ch, victim)) return; // Combat.IsSafe could wipe out victim, as it calls procs if a boss // check and see that victim is still valid if (!victim) return; Crime.CheckAttemptedMurder(ch, victim); target = new Target(victim); ch.BreakInvisibility(); break; } int beats = 0; // For quick chant if (!ch.IsClass(CharClass.Names.bard) && !ch.IsClass(CharClass.Names.psionicist)) { ch.SendText( "You begin casting...\r\n" ); if( "ventriloquate".Equals(spell.Name, StringComparison.CurrentCultureIgnoreCase )) { if( spell.ValidTargets == TargetType.singleCharacterOffensive || spell.ValidTargets == TargetType.singleCharacterRanged ) SocketConnection.Act( "$n&n begins casting an offensive spell...", ch, null, null, SocketConnection.MessageTarget.room ); else SocketConnection.Act( "$n&n begins casting...", ch, null, null, SocketConnection.MessageTarget.room ); } beats = spell.CastingTime; } else if (ch.IsClass(CharClass.Names.bard)) { ch.SendText( "You begin singing...\r\n" ); SocketConnection.Act( "$n&n starts singing...", ch, null, null, SocketConnection.MessageTarget.room ); beats = 0; } if (!ch.IsClass(CharClass.Names.psionicist) && !ch.IsClass(CharClass.Names.bard)) { // Characters with int of 110 have normal memtimes. // int of 100 worsens casting times by 10% // with an int of 55 casting times are doubled. // This may seem a bit harsh, but keep in mind any // casters are very likely to have an int above 100, as it // is their prime requisite. 120 is the max int for Grey Elves // to start. if (ch.IsClass(CharClass.Names.cleric) || ch.IsClass(CharClass.Names.druid) || ch.IsClass(CharClass.Names.paladin) || ch.IsClass(CharClass.Names.antipaladin)) { beats = ( beats * 110 ) / ch.GetCurrWis(); } else if (ch.IsClass( CharClass.Names.shaman)) { beats = ( beats * 330 ) / ( ch.GetCurrInt() + ( ch.GetCurrWis() * 2 ) ); } else { beats = ( beats * 110 ) / ch.GetCurrInt(); } if( ch.CheckSkill("quick chant", PracticeType.only_on_success) ) { beats = beats / 2; } /* * A check for impossibly long cast times...came about from a player * trying to cast when feebleminded. 100 casting time is arbitrary. */ if( beats > 100 ) { ch.SendText( "Forget it! In your present state you haven't a dream of success.\r\n" ); return; } ch.WaitState( beats ); if( CheckHypnoticPattern( ch ) ) { return; } CastData caster = new CastData(); caster.Who = ch; caster.Eventdata = Event.CreateEvent( Event.EventType.spell_cast, beats, ch, target, spell ); Database.CastList.Add( caster ); ch.SetAffectBit( Affect.AFFECT_CASTING ); } else if (ch.IsClass( CharClass.Names.psionicist)) { ch.WaitState( beats ); if( CheckHypnoticPattern( ch ) ) { return; } ch.PracticeSpell( spell ); int mana = 0; if( !ch.IsImmortal() && !ch.IsNPC() && ch.Level < ( spell.SpellCircle[ (int)ch.CharacterClass.ClassNumber ] * 4 + 1 ) && MUDMath.NumberPercent() > ((PC)ch).SpellAptitude[spell.Name]) { ch.SendText( "You lost your concentration.\r\n" ); SocketConnection.Act( "&+r$n&n&+r's face flushes white for a moment.&n", ch, null, null, SocketConnection.MessageTarget.room ); ch.CurrentMana -= mana / 2; } else { ch.CurrentMana -= mana; string buf = String.Format( "Spell {0} ({1}) being willed by {2}", spell, spell.Name, ch.Name ); Log.Trace( buf ); ch.SetAffectBit( Affect.AFFECT_CASTING ); FinishSpell( ch, spell, target ); } if( ch.CurrentPosition > Position.sleeping && ch.CurrentMana < 0 ) { ch.WaitState( 2 * Event.TICK_PER_SECOND ); ch.SendText( "&+WThat last spe&+wll w&+Las a _bitvector&+l much...&n\r\n" ); ch.CurrentPosition = Position.standing; ch.Fighting = null; SocketConnection.Act( "$n&n collapses from exhaustion&n.", ch, null, null, SocketConnection.MessageTarget.room ); ch.CurrentPosition = Position.sleeping; } if( spell.ValidTargets == TargetType.singleCharacterOffensive && victim && victim.Master != ch && victim != ch && victim.IsAwake() ) { foreach( CharData roomChar in ch.InRoom.People ) { if( victim == roomChar && !victim.Fighting ) { victim.AttackCharacter( ch ); break; } } } } else if( ch.IsClass(CharClass.Names.bard )) { ch.WaitState( 0 ); // Create an event to handle the spell CastData caster = new CastData(); caster.Who = ch; caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG, ch, target, spell ); caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 2, ch, target, spell); caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 3, ch, target, spell); caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 4, ch, target, spell); caster.Eventdata = Event.CreateEvent( Event.EventType.bard_song, Event.TICK_SONG * 5, ch, target, spell); Database.CastList.Add( caster ); ch.SetAffectBit( Affect.AFFECT_SINGING ); } return; }