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; }
public static void Heighten(CharData ch, string[] str) { if( ch == null ) return; Affect af = new Affect(); if (!ch.IsNPC() && !ch.HasSkill("heighten senses")) { ch.SendText("Your senses are as heightened as they're going to get.\r\n"); return; } if (ch.HasAffect( Affect.AffectType.skill, "heighten senses")) return; if (ch.CheckSkill("heighten senses")) { af.Value = "heighten senses"; af.Type = Affect.AffectType.skill; af.Duration = 24 + ch.Level; af.SetBitvector(Affect.AFFECT_DETECT_INVIS); ch.AddAffect(af); af.SetBitvector(Affect.AFFECT_SENSE_LIFE); ch.AddAffect(af); af.SetBitvector(Affect.AFFECT_INFRAVISION); ch.AddAffect(af); ch.SendText("Your senses are heightened.\r\n"); } return; }
/// <summary> /// Ingest a liquid. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Drink(CharData ch, string[] str) { if( ch == null ) return; Object obj = null; if (ch.IsBlind()) { return; } if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("You can't drink while you're fighting!\r\n"); return; } if (str.Length == 0 && ch.InRoom != null) { foreach (Object iobj in ch.InRoom.Contents) { if (iobj.ItemType == ObjTemplate.ObjectType.drink_container) { obj = iobj; break; } } if (!obj) { ch.SendText("Drink what?\r\n"); return; } } else { if (!(obj = ch.GetObjHere(str[0]))) { ch.SendText("You can't find it.\r\n"); return; } } // Allow bards to get twice as drunk as other classes - Xangis if (!ch.IsNPC() && !ch.IsImmortal() && ((PC)ch).Drunk > 15 && ch.IsClass(CharClass.Names.bard) && MUDMath.NumberPercent() < ch.GetCurrAgi() - ((PC)ch).Drunk) { ch.SendText("You fail to reach your mouth. *Hic*\r\n"); return; } if (!ch.IsNPC() && !ch.IsImmortal() && ((PC)ch).Drunk > 25 && ch.IsClass(CharClass.Names.bard) && MUDMath.NumberPercent() < ch.GetCurrAgi() - ((PC)ch).Drunk) { ch.SendText("You fail to reach your mouth. *Hic*\r\n"); return; } switch (obj.ItemType) { default: ch.SendText("You can't drink from that.\r\n"); break; case ObjTemplate.ObjectType.drink_container: // -1 Means a container never goes empty. if (obj.Values[1] <= 0 && obj.Values[1] != -1) { ch.SendText("It is already &+Lempty&n.\r\n"); return; } /* No drinking if you're full */ if ((!ch.IsImmortal()) && ( (!ch.IsNPC() && ((PC)ch).Thirst > 40) || (!ch.IsNPC() && ((PC)ch).Hunger > 50))) { ch.SendText("You couldn't possibly drink any more.\r\n"); return; } int liquid; if ((liquid = obj.Values[2]) >= Liquid.Table.Length) { Log.Error("Drink: bad liquid number {0}.", liquid); liquid = obj.Values[2] = 0; } SocketConnection.Act("You drink $T from $p&n.", ch, obj, Liquid.Table[liquid].Name, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n drinks $T from $p&n.", ch, obj, Liquid.Table[liquid].Name, SocketConnection.MessageTarget.room); int amount = MUDMath.NumberRange(3, 10); if (obj.Values[0] != -1) { amount = Math.Min(amount, obj.Values[1]); } ch.AdjustDrunk(amount * Liquid.Table[liquid].DrunkValue); if (!ch.IsUndead()) { ch.AdjustHunger(amount * Liquid.Table[liquid].HungerValue); if (ch.IsAffected(Affect.AFFECT_THIRST)) { ch.AdjustThirst((amount * Liquid.Table[liquid].ThirstValue) / 12); ch.SendText("That doesn't taste as &+bwet&n as it used to.\r\n"); } else { ch.AdjustThirst(amount * Liquid.Table[liquid].ThirstValue); } } else { /* If blood */ if (Liquid.Table[liquid].Name == "blood") { ch.AdjustHunger(amount * 2); ch.AdjustThirst(amount); } } if (!ch.IsNPC() && ((PC)ch).Drunk > 10) { ch.SendText("You feel &n&+gdrunk&n.\r\n"); } if (!ch.IsNPC() && ((PC)ch).Hunger > 20) { ch.SendText("You are &n&+yfull&n.\r\n"); } if (!ch.IsNPC() && ((PC)ch).Thirst > 20) { ch.SendText("You do not feel &n&+cth&+Ci&n&+cr&+Cst&n&+cy&n.\r\n"); } if (obj.Values[3] != 0 && !CharData.CheckImmune(ch, Race.DamageType.poison)) { /* The shit was poisoned ! */ Affect af = new Affect(); ch.SendText("You choke and gag.\r\n"); SocketConnection.Act("$n chokes and gags.", ch, null, null, SocketConnection.MessageTarget.room); af.Type = Affect.AffectType.spell; af.Value = "poison"; af.Duration = 3 * amount; af.AddModifier(Affect.Apply.strength, -(obj.Level / 7 + 1)); af.SetBitvector(Affect.AFFECT_POISON); ch.CombineAffect(af); } /* HOLY_WATER and UNHOLY_WATER effects */ if ((ch.IsGood() && obj.Values[2] == 27) || (ch.IsEvil() && obj.Values[2] == 28)) { int heal = MUDMath.Dice(1, 8); if (ch.Hitpoints < ch.GetMaxHit()) { ch.Hitpoints = Math.Min(ch.Hitpoints + heal, ch.GetMaxHit()); ch.UpdatePosition(); ch.SendText("You feel a little better!\r\n"); } } if ((ch.IsEvil() && obj.Values[2] == 27) || (ch.IsGood() && obj.Values[2] == 28)) { int harm = MUDMath.Dice(1, 10); ch.Hitpoints = Math.Max(ch.Hitpoints - harm, -10); ch.SendText("You choke and feel as if you'd swallowed boiling oil!\r\n"); ch.UpdatePosition(); } /* End (UN)HOLY_WATER effects */ // -1 Means a container never goes empty. if (obj.Values[1] != -1) { obj.Values[1] -= amount; if (obj.Values[1] <= 0) { ch.SendText("The container is now &+Lempty&n.\r\n"); obj.Values[1] = 0; } } break; } return; }
/// <summary> /// Eat something. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Eat(CharData ch, string[] str) { if( ch == null ) return; Object obj; if (ch.IsBlind()) return; if (ch.Fighting || ch.CurrentPosition == Position.fighting) { ch.SendText("You can't eat while you're fighting!\r\n"); return; } if (str.Length == 0) { ch.SendText("Eat what?\r\n"); return; } if (!(obj = ch.GetObjCarrying(str[0]))) { ch.SendText("You do not have that item.\r\n"); return; } if (!ch.IsImmortal()) { if (obj.ItemType != ObjTemplate.ObjectType.food && obj.ItemType != ObjTemplate.ObjectType.pill) { ch.SendText("That's not edible.\r\n"); return; } if (!ch.IsNPC() && ((PC)ch).Hunger > 40) { ch.SendText("You are too full to eat more.\r\n"); return; } } SocketConnection.Act("You consume $p&n.", ch, obj, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n inhales $p&n.", ch, obj, null, SocketConnection.MessageTarget.room); switch (obj.ItemType) { case ObjTemplate.ObjectType.food: if (!ch.IsNPC()) { int condition = ((PC)ch).Hunger; if (!ch.IsUndead()) { ch.AdjustHunger(obj.Values[0]); } if (((PC)ch).Hunger > 40) { ch.SendText("You are full.\r\n"); } else if (condition == 0 && ((PC)ch).Hunger > 0) { ch.SendText("You are no longer hungry.\r\n"); } } if (obj.Values[3] != 0 && !CharData.CheckImmune(ch, Race.DamageType.poison)) { /* The shit was poisoned! */ Affect af = new Affect(); SocketConnection.Act("$n chokes and gags.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You choke and gag.\r\n"); af.Type = Affect.AffectType.spell; af.Value = "poison"; af.Duration = 2 * obj.Values[0]; af.AddModifier(Affect.Apply.strength, -(obj.Level / 7 + 2)); af.SetBitvector(Affect.AFFECT_POISON); ch.CombineAffect(af); } break; case ObjTemplate.ObjectType.pill: { for (int i = 1; i <= 4; i++) { String spellName = SpellNumberToTextMap.GetSpellNameFromNumber(obj.Values[i]); if (String.IsNullOrEmpty(spellName)) { Log.Error("Eat: Spell number " + obj.Values[i] + " not found for pill object " + obj.ObjIndexNumber + ". Make sure it's in the SpellNumberToTextMap."); } Spell spell = StringLookup.SpellLookup(spellName); if (!spell) { Log.Error("Eat: Spell '" + spellName + "' not found for pill object " + obj.ObjIndexNumber + ". Make sure it's in the spells file."); } else { spell.Invoke(ch, obj.Values[0], ch); } } } break; } if (!ch.IsNPC() || (ch.IsNPC() && ch.IsAffected(Affect.AFFECT_CHARM))) { obj.RemoveFromWorld(); } return; }
/// <summary> /// Song of warding, protective. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongWarding( CharData ch, Spell spell, int level, Target target ) { Affect af = new Affect(); foreach( CharData victim in ch.InRoom.People ) { af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 7; af.AddModifier(Affect.Apply.save_spell, 0 - ( ( level / 5 ) + 1 )); af.AddModifier(Affect.Apply.save_paralysis, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_petrification, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_poison, 0 - ((level / 5) + 1)); af.AddModifier(Affect.Apply.save_breath, 0 - ((level / 5) + 1)); af.SetBitvector(Affect.AFFECT_NONE); victim.AddAffect(af); } return true; }
public static void ApplyPoison( CharData ch ) { Affect af = new Affect(); bool isSpell = false; foreach (Affect aff in ch.Affected) { if( aff.Type == Affect.AffectType.spell && aff.Value == "poison" ) { isSpell = true; } else if ((aff.Type == Affect.AffectType.skill && aff.Value == "poison weapon" || aff.Value == "poison bite") ) { foreach (AffectApplyType apply in aff.Modifiers) { if (apply.Location != Affect.Apply.none || ch.IsAffected(Affect.AFFECT_SLOW_POISON) && MUDMath.NumberBits(1) == 0) continue; Poison.Type poisonType = (Poison.Type)apply.Amount; int dam; switch (poisonType) { case Poison.Type.damage: SocketConnection.Act("$n&n goes into a brief siezure as the poison courses through $s body.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("Your muscles twitch randomly as the poison courses through your body.\r\n"); dam = MUDMath.Dice(1, 10); if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) InflictDamage(ch, ch, dam, "poison weapon", ObjTemplate.WearLocation.none, AttackType.DamageType.poison); else InflictDamage(ch, ch, dam / 2, "poison weapon", ObjTemplate.WearLocation.none, AttackType.DamageType.poison); return; case Poison.Type.attributes: if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) { int lev = aff.Level; ch.AffectStrip(Affect.AffectType.skill, "poison weapon"); af.Type = Affect.AffectType.skill; af.Value = "poison"; af.Duration = lev / 4; af.Level = lev; af.AddModifier(Affect.Apply.strength, 0 - MUDMath.Dice(1, 20)); af.AddModifier(Affect.Apply.dexterity, 0 - MUDMath.Dice(1, 20)); af.AddModifier(Affect.Apply.agility, 0 - MUDMath.Dice(1, 20)); af.AddModifier(Affect.Apply.constitution, 0 - MUDMath.Dice(1, 20)); af.SetBitvector(Affect.AFFECT_POISON); ch.AddAffect(af); ch.SendText("You suddenly feel quite weak as the poison is distributed through your body.&n\r\n"); SocketConnection.Act("$n&n pales visibly and looks much weaker.", ch, null, null, SocketConnection.MessageTarget.room); return; } ch.SendText("You feel the poison working its way into your system.\r\n"); InflictDamage(ch, ch, 2, "poison weapon", ObjTemplate.WearLocation.none, AttackType.DamageType.poison); break; case Poison.Type.damage_major: dam = MUDMath.Dice(10, 10); SocketConnection.Act("$n&n screams in agony as the poison courses through $s body.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("&+RYour blood is on fire!&n\r\n"); if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) InflictDamage(ch, ch, dam, "poison weapon", ObjTemplate.WearLocation.none, AttackType.DamageType.poison); else InflictDamage(ch, ch, dam / 2, "poison weapon", ObjTemplate.WearLocation.none, AttackType.DamageType.poison); return; case Poison.Type.minor_para: if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) { ch.AffectStrip(Affect.AffectType.skill, "poison_weapon"); af.Value = "poison"; af.Type = Affect.AffectType.skill; af.Duration = MUDMath.NumberRange(1, 10); af.SetBitvector(Affect.AFFECT_MINOR_PARA); ch.AddAffect(af); ch.SendText("&+YYou are paralyzed!&n\r\n"); StopFighting(ch, false); SocketConnection.Act("$n&n&+y is suddenly overcome with rigor and cannot move.&n", ch, null, null, SocketConnection.MessageTarget.room); } break; case Poison.Type.minor_para_extended: if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) { ch.AffectStrip(Affect.AffectType.skill, "poison_weapon"); af.Value = "poison"; af.Type = Affect.AffectType.skill; af.Duration = MUDMath.NumberRange(5, 30); af.SetBitvector(Affect.AFFECT_MINOR_PARA); ch.AddAffect(af); ch.SendText("&+YYou are paralyzed!&n\r\n"); StopFighting(ch, false); SocketConnection.Act("$n&n&+y is suddenly overcome with rigor and cannot move.&n", ch, null, null, SocketConnection.MessageTarget.room); } break; case Poison.Type.major_para: if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) { ch.AffectStrip(Affect.AffectType.skill, "poison_weapon"); af.Value = "poison"; af.Type = Affect.AffectType.skill; af.Duration = MUDMath.NumberRange(1, 10); af.SetBitvector(Affect.AFFECT_HOLD); ch.AddAffect(af); ch.SendText("&+YYou are paralyzed!&n\r\n"); StopFighting(ch, false); SocketConnection.Act("$n&n&+y is suddenly overcome with rigor and cannot move.&n", ch, null, null, SocketConnection.MessageTarget.room); } break; case Poison.Type.major_para_extended: if (!Magic.SpellSavingThrow(aff.Level, ch, AttackType.DamageType.poison)) { ch.AffectStrip(Affect.AffectType.skill, "poison_weapon"); af.Value = "poison"; af.Type = Affect.AffectType.skill; af.Duration = MUDMath.NumberRange(5, 30); af.SetBitvector(Affect.AFFECT_HOLD); ch.AddAffect(af); ch.SendText("&+YYou are paralyzed!&n\r\n"); StopFighting(ch, false); SocketConnection.Act("$n&n&+y is suddenly overcome with rigor and cannot move.&n", ch, null, null, SocketConnection.MessageTarget.room); } break; case Poison.Type.perm_constitution: // TODO: Implement perm constitution loss from poison. break; case Poison.Type.perm_hitpoints: // TODO: Implement perm hitpoint loss from poison. break; case Poison.Type.near_death: // TODO: Implement "near death" poison - one that drains HP very quickly but does not kill. break; default: Log.Error("Unimplemented or unknown poison type: " + poisonType.ToString()); break; } } } //end if } if( isSpell ) { //normal poison from the spell ch.SendText( "You shiver and suffer.\r\n" ); SocketConnection.Act( "$n&n shivers and suffers.", ch, null, null, SocketConnection.MessageTarget.room ); if (!ch.IsAffected(Affect.AFFECT_SLOW_POISON)) { InflictSpellDamage( ch, ch, 2, "poison", AttackType.DamageType.poison ); } else { // Slow poison gives them a 20% chance of avoiding damage // and does half damage when it does hit them, giving // them 40% as much damage overall as a non-slowed person if( MUDMath.NumberPercent() < 80 ) InflictSpellDamage( ch, ch, 1, "poison", AttackType.DamageType.poison ); } } else { //normal poison from a bite or weapon ch.SendText( "You shiver and suffer.\r\n" ); SocketConnection.Act( "$n&n shivers and suffers.", ch, null, null, SocketConnection.MessageTarget.room ); if (!ch.IsAffected(Affect.AFFECT_SLOW_POISON)) { InflictDamage( ch, ch, 2, "poison", ObjTemplate.WearLocation.none, AttackType.DamageType.poison ); } else { // Slow poison gives them a 20% chance of avoiding damage // and does half damage when it does hit them, giving // them 40% as much damage overall as a non-slowed person if( MUDMath.NumberPercent() < 80 ) InflictDamage( ch, ch, 1, "poison", ObjTemplate.WearLocation.none, AttackType.DamageType.poison ); } } }
public static void Shadow(CharData ch, string[] str) { if( ch == null ) return; Affect af = new Affect(); if (!ch.IsNPC() && !ch.HasSkill("shadow form")) { ch.SendText("You don't know how to take shadow form.\r\n"); return; } ch.SendText("You attempt to move in the shadows.\r\n"); ch.AffectStrip( Affect.AffectType.skill, "shadow form"); if (ch.CheckSkill("shadow form")) { af.Value = "shadow form"; af.Type = Affect.AffectType.skill; af.Duration = ch.Level; af.SetBitvector(Affect.AFFECT_SNEAK); ch.AddAffect(af); } ch.WaitState(10); return; }
/// <summary> /// Song of obscrurement. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongObscurement( CharData ch, Spell spell, int level, Target target ) { Affect af = new Affect(); foreach( CharData victim in ch.InRoom.People ) { if( victim.IsAffected( Affect.AFFECT_MINOR_INVIS ) || victim.IsAffected( Affect.AFFECT_INVISIBLE ) ) return true; SocketConnection.Act( "$n&n fades out of existence.", ch, null, null, SocketConnection.MessageTarget.room ); ch.SendText( "You vanish.\r\n" ); af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 6; af.SetBitvector( Affect.AFFECT_MINOR_INVIS ); victim.AddAffect(af); } return true; }
public static void Berzerk(CharData ch, string[] str) { if( ch == null ) return; Affect af = new Affect(); /* Don't allow charmed mobs to do this, check player's level */ if ((ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && !ch.HasSkill("berzerk"))) { ch.SendText("You're not enough of a warrior to enter a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n.\r\n"); return; } if (ch.IsAffected(Affect.AFFECT_BERZERK)) { if (MUDMath.NumberPercent() + 10 > ((PC)ch).SkillAptitude["berzerk"]) { ch.SendText("You failed to calm yourself down!\r\n"); ch.WaitState(Skill.SkillList["berzerk"].Delay); return; } ch.SendText("You no longer see targets everywhere.\r\n"); ch.RemoveAffect(Affect.AFFECT_BERZERK); ch.WaitState(Skill.SkillList["berzerk"].Delay); return; } ch.SendText("Your slam your weapon into yourself and &+Rbl&n&+ro&+Ro&n&+rd&n splatters all over!\r\n"); ch.SendText("The sight of &+Rbl&n&+ro&+Ro&n&+rd&n begins to drive you crazy!\r\n"); if (ch.CheckSkill("berzerk")) { af.Value = "berzerk"; af.Type = Affect.AffectType.skill; af.Duration = MUDMath.Dice(1, 2); af.AddModifier( Affect.Apply.hitroll, Math.Max(ch.Level / 6, 2)); af.AddModifier( Affect.Apply.damroll, Math.Max(ch.Level / 6, 2)); af.AddModifier( Affect.Apply.ac, (ch.Level / 2)); af.AddModifier( Affect.Apply.max_constitution, MUDMath.Dice(5, 9)); af.AddModifier( Affect.Apply.agility, 0 - MUDMath.Dice(5, 9)); af.AddModifier( Affect.Apply.max_strength, MUDMath.Dice(5, 9)); af.SetBitvector(Affect.AFFECT_BERZERK); ch.AddAffect(af); ch.SendText("You are overcome by &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!\r\n"); SocketConnection.Act("$n has slipped into a &+RBl&n&+ro&+Ro&n&+rd&+L Rage&n!!", ch, null, null, SocketConnection.MessageTarget.room); return; } ch.SendText("You get a little angry, but fail to call up a &+Rblood rage&n.\r\n"); return; }
/// <summary> /// Apply poison to a weapon. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void PoisonWeapon(CharData ch, string[] str) { if (ch == null) { return; } Object obj; Object pobj = null; Affect af = new Affect(); /* Don't allow mobs or unskilled pcs to do this */ if (ch.IsNPC() || (!ch.IsNPC() && !ch.HasSkill("poison weapon"))) { ch.SendText("What do you think you are, a thief?\r\n"); return; } if (str.Length == 0) { ch.SendText("What are you trying to poison?\r\n"); return; } if (ch.Fighting != null) { ch.SendText("While you're fighting? Nice try.\r\n"); return; } if (!(obj = ch.GetObjCarrying(str[0]))) { ch.SendText("You do not have that weapon.\r\n"); return; } if (obj.ItemType != ObjTemplate.ObjectType.weapon) { ch.SendText("That item is not a weapon.\r\n"); return; } if (obj.HasFlag(ObjTemplate.ITEM_POISONED)) { ch.SendText("That weapon is already poisoned.\r\n"); return; } if (obj.Values[0] != 2) { ch.SendText("You don't have enough poison to cover that!\r\n"); return; } /* Now we have a valid weapon...check to see if we have the poison. */ foreach (Object iobj in ch.Carrying) { // here is where we should check to see if they have poison if (iobj.ItemType == ObjTemplate.ObjectType.drink_container && iobj.Values[2] == 27) { pobj = iobj; break; } } if (!pobj) { ch.SendText("You do not have any poison.\r\n"); return; } if (pobj.Values[1] <= 0 && pobj.Values[1] != -1) { SocketConnection.Act("Sorry, $p&n seems to be empty.", ch, pobj, null, SocketConnection.MessageTarget.character); return; } ch.WaitState(Skill.SkillList["poison weapon"].Delay); /* Check the skill percentage */ if (!ch.CheckSkill("poison weapon")) { ch.SendText("You failed and spill some on yourself. &+ROuch!&n\r\n"); Combat.InflictDamage(ch, ch, ch.Level, "poison weapon", ObjTemplate.WearLocation.none, AttackType.DamageType.poison); SocketConnection.Act("$n spills the &+Gpoison&n all over!", ch, null, null, SocketConnection.MessageTarget.room); pobj.Values[1] -= 2; return; } /* Can't have people smearing gunk on artifacts */ if (obj.InsultArtifact(ch)) { pobj.Values[1]--; return; } SocketConnection.Act("You apply the &+Gpoison&n to $p&n, which glistens wickedly!", ch, obj, null, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n pours the &+Gli&n&+gq&+Gu&n&+gid&n over $p&n, which glistens wickedly!", ch, obj, null, SocketConnection.MessageTarget.room); af.Value = "poison weapon"; af.Type = Affect.AffectType.skill; af.Duration = ch.Level + MUDMath.Dice(4, ch.Level / 2); af.AddModifier(Affect.Apply.none, pobj.Values[3]); af.Level = ch.Level; af.SetBitvector(Affect.AFFECT_POISON); obj.AddAffect(af); // Consume one unit of the poison source. pobj.Values[1]--; return; }
/// <summary> /// Paladin "lay hands" healing command. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void LayHands(CharData ch, string[] str) { if( ch == null ) return; Affect af = new Affect(); if (ch.Level <= Limits.LEVEL_AVATAR && !ch.IsClass(CharClass.Names.paladin)) { ch.SendText("&nYou aren't holy enough to do that!\r\n"); return; } if (ch.IsAffected(Affect.AFFECT_LAYHANDS_TIMER)) { ch.SendText("&nIt is too soon to accomplish that!\r\n"); return; } if (str.Length == 0) { ch.SendText("&nLayhands on whom?\r\n"); return; } CharData victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("&nThey're not here.\r\n"); return; } if (victim != ch && ch.Fighting) { ch.SendText("&nYou can only layhands on yourself while fighting.\r\n"); return; } if (victim.Hitpoints < victim.GetMaxHit()) victim.Hitpoints = Math.Min(victim.Hitpoints + 300, victim.GetMaxHit()); victim.UpdatePosition(); if (ch != victim) { SocketConnection.Act("You lay your hands upon $N.", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n lays $s hands upon you.", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n lays $s hands upon $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { ch.SendText("&nYou layhands upon yourself.\r\n"); SocketConnection.Act("$n&n lays hands upon $mself&n.", ch, null, null, SocketConnection.MessageTarget.room); } victim.SendText("&+WYou feel a warm glow!&n\r\n"); if (ch.Level >= Limits.LEVEL_AVATAR) return; af.Value = "layhands timer"; af.Type = Affect.AffectType.skill; af.Duration = 24; af.SetBitvector(Affect.AFFECT_LAYHANDS_TIMER); ch.AddAffect(af); }
/// <summary> /// Innate command. Shows and activates innate abilitiies. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Innate(CharData ch, string[] str) { if( ch == null ) return; string text; Affect af = new Affect(); // Use innates here if (str.Length > 0 && !String.IsNullOrEmpty(str[0])) { if (!MUDString.IsPrefixOf(str[0], "strength")) { if (ch.HasInnate(Race.RACE_STRENGTH)) { if (ch.IsAffected(Affect.AFFECT_STRENGTH_INCREASED)) { ch.SendText("You are already affected by strength."); return; } if (ch.HasInnateTimer(InnateTimerData.Type.strength)) { ch.SendText("You need to rest a bit first.\r\n"); return; } af.Type = Affect.AffectType.spell; af.Value = "strength"; af.Duration = MUDMath.Dice(8, 5); af.AddModifier(Affect.Apply.strength, MUDMath.Dice(2, 4) + 15); af.SetBitvector(Affect.AFFECT_STRENGTH_INCREASED); ch.AddAffect(af); ch.SendText("You feel stronger.\r\n"); ch.AddInnateTimer(InnateTimerData.Type.strength, 24); ch.WaitState(14); } else { ch.SendText("You don't know how to do that.\r\n"); return; } } else if (!MUDString.IsPrefixOf(str[0], "levitate")) { if (ch.HasInnate(Race.RACE_LEVITATE)) { if (ch.IsAffected( Affect.AFFECT_LEVITATE)) { ch.SendText("You are already levitating."); return; } if (ch.HasInnateTimer(InnateTimerData.Type.levitate)) { ch.SendText("You need to rest a bit first.\r\n"); return; } af.Type = Affect.AffectType.spell; af.Value = "levitation"; af.Duration = MUDMath.Dice(8, 5); af.SetBitvector(Affect.AFFECT_LEVITATE); ch.AddAffect(af); ch.SendText("Your feet rise off the ground.\r\n"); ch.AddInnateTimer(InnateTimerData.Type.levitate, 24); ch.WaitState(6); } else { ch.SendText("You don't know how to do that.\r\n"); return; } } else if (!MUDString.IsPrefixOf(str[0], "faerie")) { if (ch.HasInnate(Race.RACE_FAERIE_FIRE)) { CharData victim = ch.GetCharRoom(str[0]); if (victim == null) ch.SendText("You do not see them here."); else { Spell spl = Spell.SpellList["faerie fire"]; if (spl != null) { spl.Invoke(ch, ch.Level, victim); } } } else { ch.SendText("You don't know how to do that.\r\n"); return; } } else if (!MUDString.IsPrefixOf(str[0], "invisibility")) { if (ch.HasInnate(Race.RACE_INVIS)) { if (ch.IsAffected( Affect.AFFECT_INVISIBLE)) { ch.SendText("You are already invisible!\r\n"); return; } if (ch.HasInnateTimer(InnateTimerData.Type.invisibility)) { ch.SendText("You need to rest a bit first.\r\n"); return; } af.Type = Affect.AffectType.spell; af.Value = "invisibility"; af.Duration = MUDMath.Dice(2, 8) + 4; af.SetBitvector(Affect.AFFECT_INVISIBLE); SocketConnection.Act("$n&n fades out of existence.", ch, null, null, SocketConnection.MessageTarget.room); ch.SendText("You vanish.\r\n"); ch.AddAffect(af); ch.AddInnateTimer(InnateTimerData.Type.invisibility, 24); ch.WaitState(24); } else { ch.SendText("You don't know how to do that.\r\n"); return; } } else if (!MUDString.IsPrefixOf(str[0], "enlarge")) { if (ch.HasInnate(Race.RACE_ENLARGE)) { if (ch.IsAffected(Affect.AFFECT_ENLARGED)) { ch.SendText("You are already enlarged.\r\n"); return; } if (ch.HasInnateTimer(InnateTimerData.Type.enlarge)) { ch.SendText("You need to rest a bit first.\r\n"); return; } af.Type = Affect.AffectType.spell; af.Value = "enlarge"; af.Duration = MUDMath.Dice(8, 5); af.AddModifier(Affect.Apply.size, 1); af.SetBitvector(Affect.AFFECT_NONE); ch.AddAffect(af); ch.SendText("&nYou grow to almost twice your normal size!\r\n"); SocketConnection.Act("$n&n grows to almost twice $s normal size!&n", ch, null, null, SocketConnection.MessageTarget.room); ch.AddInnateTimer(InnateTimerData.Type.enlarge, 24); ch.WaitState(10); } else { ch.SendText("You don't know how to do that.\r\n"); return; } } else if (!MUDString.IsPrefixOf(str[0], "shift")) { if (str.Length > 1 && !MUDString.IsPrefixOf(str[1], "astral")) { if (ch.HasInnate(Race.RACE_SHIFT_ASTRAL)) { if (ch.HasInnateTimer(InnateTimerData.Type.shift_astral)) { ch.SendText("You need to rest a bit first.\r\n"); return; } Spell spell = StringLookup.SpellLookup("plane shift"); if (!spell) { ch.SendText("Something seems to be blocking your ability to shift."); Log.Error("Innate Shift: 'plane shift' spell not found. Check the spells file."); return; } spell.Invoke(ch, ch.Level, new Target(str[1])); ch.AddInnateTimer(InnateTimerData.Type.shift_astral, 8); ch.WaitState(10); } else { ch.SendText("You don't know how to do that.\r\n"); return; } } else if (str.Length > 1 && !MUDString.IsPrefixOf(str[1], "prime")) { if (ch.HasInnate(Race.RACE_SHIFT_PRIME)) { if (ch.HasInnateTimer(InnateTimerData.Type.shift_prime)) { ch.SendText("You need to rest a bit first.\r\n"); return; } Spell spell = StringLookup.SpellLookup("plane shift"); if (!spell) { ch.SendText("Something seems to be blocking your ability to shift."); Log.Error("Innate Shift: 'plane shift' spell not found. Check the spells file."); return; } spell.Invoke(ch, ch.Level, new Target(str[1])); ch.AddInnateTimer(InnateTimerData.Type.shift_prime, 8); ch.WaitState(10); } else { ch.SendText("You don't know how to do that.\r\n"); return; } } } else { ch.SendText("That's not implemented yet. :(\r\n"); } return; } text = String.Format("&+BInnate abilities available to your race and class:&n\r\n"); if (ch.HasInnate(Race.RACE_BODYSLAM)) text += "&n bodyslam\r\n"; if (ch.HasInnate(Race.RACE_CHARGE)) text += "&n charge\r\n"; if (ch.HasInnate(Race.RACE_FLY)) text += "&n fly\r\n"; if (ch.HasInnate(Race.RACE_PASSDOOR)) text += "&n pass door\r\n"; if (ch.HasInnate(Race.RACE_SWIM)) text += "&n swim\r\n"; if (ch.HasInnate(Race.RACE_WATERBREATH)) text += "&n water breathing\r\n"; if (ch.HasInnate(Race.RACE_INFRAVISION)) text += "&n infravision\r\n"; if (ch.HasInnate(Race.RACE_ULTRAVISION)) text += "&n ultravision\r\n"; if (ch.HasInnate(Race.RACE_DETECT_ALIGN) || ch.IsClass(CharClass.Names.antipaladin) || ch.IsClass(CharClass.Names.paladin)) text += "&n detect align\r\n"; if (ch.HasInnate(Race.RACE_DETECT_INVIS)) text += "&n detect invis\r\n"; if (ch.HasInnate(Race.RACE_DETECT_HIDDEN)) text += "&n detect hidden\r\n"; if (ch.HasInnate(Race.RACE_MUTE)) text += "&n mute\r\n"; if (ch.HasInnate(Race.RACE_DOORBASH)) text += "&n doorbash\r\n"; if (ch.HasInnate(Race.RACE_SHRUG)) text += "&n shrug\r\n"; if (ch.HasInnate(Race.RACE_ODSNEAK)) text += "&n outdoor sneak\r\n"; if (ch.HasInnate(Race.RACE_UDSNEAK)) text += "&n underdark sneak\r\n"; if (ch.HasInnate(Race.RACE_STRENGTH)) text += "&n strength\r\n"; if (ch.HasInnate(Race.RACE_FAERIE_FIRE)) text += "&n faerie fire\r\n"; // if( ch.HasInnate( Race.RACE_STEAL )) // buf += "&n steal\r\n" ); if (ch.HasInnate(Race.RACE_ENLARGE)) text += "&n enlarge\r\n"; if (ch.HasInnate(Race.RACE_INVIS)) text += "&n invisibility\r\n"; // if( ch.HasInnate( Race.RACE_SUMMON_HOARDE )) // buf += "&n summon hoarde\r\n" ); if (ch.HasInnate(Race.RACE_SHIFT_PRIME)) text += "&n shift prime\r\n"; if (ch.HasInnate(Race.RACE_SHIFT_ASTRAL)) text += "&n shift astral\r\n"; if (ch.HasInnate(Race.RACE_LEVITATE)) text += "&n levitate\r\n"; if (ch.HasInnate(Race.RACE_BITE)) text += "&n bite\r\n"; ch.SendText(text); return; }
/* * To be used only with skills, not spells. */ static void InflictPoison( string name, int level, bool type, CharData ch, CharData victim ) { Affect af = new Affect(); if( Magic.SpellSavingThrow( level, victim, AttackType.DamageType.poison ) ) return; int typ; if (type) typ = 1; else typ = 0; af.Value = name; af.Type = Affect.AffectType.skill; af.Level = level; af.Duration = level / 4; af.AddModifier(Affect.Apply.none, typ ); af.SetBitvector( Affect.AFFECT_POISON ); victim.CombineAffect(af); if( ch != victim ) ch.SendText( "You have poisoned your victim.\r\n" ); victim.SendText( "&+GYou don't feel very well.&n\r\n" ); return; }
/// <summary> /// Song of idiocy. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongIdiocy( CharData ch, Spell spell, int level, Target target ) { Affect af = new Affect(); foreach( CharData victim in ch.InRoom.People ) { if (victim.IsAffected(Affect.AFFECT_FEEBLEMIND) || Magic.SpellSavingThrow( level, victim, AttackType.DamageType.black_magic ) ) { ch.SendText( "You failed!\r\n" ); continue; } af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 9; af.AddModifier(Affect.Apply.intelligence, 0 - (level + 15)); af.SetBitvector(Affect.AFFECT_FEEBLEMIND); victim.AddAffect(af); SocketConnection.Act( "A dumb look crosses $n&n's face and $e starts to drool.", victim, null, null, SocketConnection.MessageTarget.room ); victim.SendText( "You feel _REALLY_ dumb.\r\n" ); } return true; }
/// <summary> /// Innate mount summoning command for antipaladins and paladins. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void SummonMount(CharData ch, string[] str) { MobTemplate mobTemplate; Affect af = new Affect(); int mountNumber = ch.CharacterClass.CanSummonMountNumber; if (mountNumber == 0) { ch.SendText("You scream and yell for a mount. Strangely nothing comes.\r\n"); return; } if (ch.IsAffected( Affect.AFFECT_SUMMON_MOUNT_TIMER)) { ch.SendText("&nIt is too soon to accomplish that!\r\n"); return; } // Look to see if they already have a mount. foreach (CharData previousMount in Database.CharList) { if (previousMount.Master == ch && previousMount.IsNPC() && previousMount.MobileTemplate != null && (previousMount.MobileTemplate.IndexNumber == mountNumber)) { ch.SendText("You already have a mount!\r\n"); return; } } // If not let found, them summon one. mobTemplate = Database.GetMobTemplate(mountNumber); if (mobTemplate == null) { Log.Error("SummonMount: Invalid MobTemplate!", 0); return; } CharData mount = Database.CreateMobile(mobTemplate); // Simulate the poor mount running across the world. // They arrive with partially depleted moves. mount.CurrentMoves -= MUDMath.Dice(4, 40); CharData.AddFollower(mount, ch); mount.SetAffectBit(Affect.AFFECT_CHARM); mount.SetActionBit(MobTemplate.ACT_NOEXP); mount.AddToRoom(ch.InRoom); ch.WaitState(MUDMath.FuzzyNumber(Skill.SkillList["summon mount"].Delay)); SocketConnection.Act("$n&n trots up to you.", mount, null, ch, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n trots up to $N&n.", mount, null, ch, SocketConnection.MessageTarget.everyone_but_victim); if (ch.IsImmortal()) { return; } af.Value = "summon mount"; af.Type = Affect.AffectType.skill; af.Duration = 48; af.SetBitvector(Affect.AFFECT_SUMMON_MOUNT_TIMER); ch.AddAffect(af); return; }
/// <summary> /// Song of nightmares. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongNightmares( CharData ch, Spell spell, int level, Target target ) { Affect af = new Affect(); foreach( CharData victim in ch.InRoom.People ) { if (victim.IsAffected(Affect.AFFECT_FEAR) || Magic.SpellSavingThrow(level, victim, AttackType.DamageType.black_magic ) ) { ch.SendText( "You have failed.\r\n" ); ch.SendText( "You resist the urge to panic.\r\n" ); continue; } af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = 1 + ( level / 7 ); af.SetBitvector( Affect.AFFECT_FEAR ); victim.AddAffect(af); SocketConnection.Act( "$N&n is scared!", ch, null, victim, SocketConnection.MessageTarget.character ); victim.SendText( "You are scared!\r\n" ); SocketConnection.Act( "$N&n is scared!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim ); CommandType.Interpret( victim, "flee" ); if( victim.IsNPC() ) Combat.StartFearing( victim, ch ); } return true; }
/// <summary> /// Capture command - restrain another character. /// </summary> /// <param name="ch"></param> /// <param name="str"></param> public static void Capture(CharData ch, string[] str) { if( ch == null ) return; CharData victim; Affect af = new Affect(); /* Check player's level and class, allow mobs to do this too */ if ((!ch.HasSkill("capture"))) { ch.SendText("You couldn't capture a dead rat.\r\n"); return; } if (str.Length == 0) { victim = ch.Fighting; if (!victim) { ch.SendText("Capture whom?\r\n"); return; } } else /* argument supplied */ { victim = ch.GetCharRoom(str[0]); if (!victim) { ch.SendText("They aren't here.\r\n"); return; } } if (ch.Fighting && ch.Fighting != victim) { ch.SendText("Take care of the person you are fighting first!\r\n"); return; } if (!ch.IsImmortal()) { ch.WaitState(Skill.SkillList["capture"].Delay); } Object rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_one); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) { rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_two); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) { rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_three); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) { rope = Object.GetEquipmentOnCharacter(ch, ObjTemplate.WearLocation.hand_four); if (!rope || rope.ItemType != ObjTemplate.ObjectType.rope) rope = null; } } } if (!rope) { ch.SendText("You must have some rope to tie someone up!\r\n"); return; } rope.RemoveFromWorld(); /* only appropriately skilled PCs and uncharmed mobs */ if ((ch.IsNPC() && !ch.IsAffected( Affect.AFFECT_CHARM)) || (!ch.IsNPC() && MUDMath.NumberPercent() < ((PC)ch).SkillAptitude["capture"] / 4)) { victim.AffectStrip( Affect.AffectType.skill, "capture"); af.Value = "capture"; af.Type = Affect.AffectType.skill; af.Duration = 3 + ((ch.Level) / 8); af.SetBitvector(Affect.AFFECT_BOUND); victim.AddAffect(af); SocketConnection.Act("You have captured $M!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n has captured you!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n has captured $N&n.", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } else { SocketConnection.Act("You failed to capture $M. Uh oh!", ch, null, victim, SocketConnection.MessageTarget.character); SocketConnection.Act("$n&n tried to capture you! Get $m!", ch, null, victim, SocketConnection.MessageTarget.victim); SocketConnection.Act("$n&n attempted to capture $N&n, but failed!", ch, null, victim, SocketConnection.MessageTarget.everyone_but_victim); } /* go for the one who wanted to fight :) */ if (ch.IsNPC() && ch.IsAffected( Affect.AFFECT_CHARM) && !victim.Fighting) { victim.AttackCharacter(ch.Master); } else if (!victim.Fighting) { victim.AttackCharacter(ch); } return; }
/// <summary> /// Song of slowness. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongSlowness( CharData ch, Spell spell, int level, Target target ) { Affect af = new Affect(); foreach( CharData victim in ch.InRoom.People ) { if( Magic.SpellSavingThrow( level, victim, AttackType.DamageType.magic_other ) ) { ch.SendText( "You failed!\r\n" ); continue; } // Removes haste, takes two castings to make a hasted person slowed if (victim.IsAffected( Affect.AFFECT_HASTE)) { victim.RemoveAffect(Affect.AFFECT_HASTE); victim.SendText( "You slow to your normal speed.\r\n" ); continue; } if (victim.IsAffected(Affect.AFFECT_SLOWNESS)) continue; af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = 6; af.SetBitvector( Affect.AFFECT_SLOWNESS ); victim.AddAffect(af); SocketConnection.Act( "&+R$n&+R moves much more slowly.&n", victim, null, null, SocketConnection.MessageTarget.room ); victim.SendText( "&+RYou feel yourself slowing down.&n\r\n" ); } return true; }
/// <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> /// Song of weakness. /// </summary> /// <param name="ch"></param> /// <param name="spell"></param> /// <param name="level"></param> /// <param name="target"></param> /// <returns></returns> public static bool SongWeakling( CharData ch, Spell spell, int level, Target target ) { Affect af = new Affect(); foreach( CharData victim in ch.InRoom.People ) { if (victim.IsAffected( Affect.AFFECT_STRENGTH_REDUCED) || Magic.SpellSavingThrow( level, victim, AttackType.DamageType.black_magic ) ) continue; af.Type = Affect.AffectType.song; af.Value = spell.Name; af.Duration = level / 7; af.AddModifier(Affect.Apply.strength, -( level / 2 )); af.SetBitvector(Affect.AFFECT_STRENGTH_REDUCED); if( level > 25 ) { af.AddModifier( Affect.Apply.damroll, 0 - ( level / 7 )); } victim.AddAffect(af); SocketConnection.Act( "$n&n looks weaker.", victim, null, null, SocketConnection.MessageTarget.room ); victim.SendText( "You feel weaker.\r\n" ); } return true; }
/// <summary> /// Updates all characters, mobs and players alike. /// /// This function is performance sensitive. /// </summary> static void CharacterUpdate() { CharData ch; CharData chSave = null; CharData chQuit = null; _hunger = ( ( ++_hunger ) % 16 ); DateTime saveTime = Database.SystemData.CurrentTime; for( int i = (Database.CharList.Count - 1); i >= 0; i-- ) { ch = Database.CharList[i]; if( !ch.InRoom ) { continue; } if( ch.CurrentPosition == Position.stunned ) ch.UpdatePosition(); if( ch.CurrentPosition == Position.dead ) { ch.SendText( "&+lYour soul finally leaves your body.&n\r\n" ); SocketConnection.Act( "&+l$n&+l's corpse grows &+bcold&+l.", ch, null, null, SocketConnection.MessageTarget.room ); Combat.KillingBlow( ch, ch ); continue; } if( ch.CurrentPosition == Position.fighting && !ch.Fighting ) ch.CurrentPosition = Position.standing; if( !ch.IsNPC() ) ch.UpdateInnateTimers(); Affect affect; for( int j = (ch.Affected.Count - 1); j >= 0; j-- ) { affect = ch.Affected[j]; if( affect.Duration > 0 ) affect.Duration--; else if( affect.Duration < 0 ) { // Permanent affect, not on a timer. } else { if( affect.Type == Affect.AffectType.skill && Skill.SkillList[ affect.Value ].WearOffMessage.Length > 0 ) { ch.SendText(Skill.SkillList[affect.Value].WearOffMessage); ch.SendText( "\r\n" ); if( affect.Value == "vampiric bite" ) ch.SetPermRace( Race.RACE_VAMPIRE ); } else if (affect.Type == Affect.AffectType.spell && Spell.SpellList[affect.Value].MessageWearOff.Length > 0) { ch.SendText( Spell.SpellList[ affect.Value ].MessageWearOff ); ch.SendText( "\r\n" ); } else if( affect.Type == Affect.AffectType.song && Database.SongList[ affect.Value ].MessageWearOff.Length > 0 ) { ch.SendText( Database.SongList[ affect.Value ].MessageWearOff ); ch.SendText( "\r\n" ); } ch.RemoveAffect( ch.Affected[j] ); } } if( ch.IsAffected( Affect.AFFECT_VACANCY ) && !ch.IsAffected( Affect.AFFECT_HIDE ) ) { ch.SendText( "You become part of your surroundings.\r\n" ); SocketConnection.Act( "$n&n fades from view.", ch, null, null, SocketConnection.MessageTarget.room ); ch.SetAffectBit( Affect.AFFECT_HIDE ); } // Careful with the damages here, MUST NOT refer to ch after damage taken, // as it may be lethal damage (on NPC). if (ch.IsAffected(Affect.AFFECT_DISEASE)) { Affect plague = new Affect(); int level = 0; SocketConnection.Act( "$n&n writhes in agony as plague sores erupt from $s skin.", ch, null, null, SocketConnection.MessageTarget.room ); ch.SendText( "You writhe in agony from the plague.\r\n" ); foreach (Affect af in ch.Affected) { if (af.Type == Affect.AffectType.spell && af.Value == "plague") { level = af.Level; break; } } if( level == 0 ) { ch.RemoveAffect( Affect.AFFECT_DISEASE ); continue; } if( level == 1 ) continue; plague.Type = Affect.AffectType.spell; plague.Value = "plague"; plague.Level = level - 1; plague.Duration = MUDMath.NumberRange( 1, 2 * plague.Level ); plague.AddModifier(Affect.Apply.strength, -5); plague.SetBitvector( Affect.AFFECT_DISEASE ); int save = plague.Level; foreach( CharData ivch in ch.InRoom.People ) { if( save != 0 && !Magic.SpellSavingThrow( save, ivch, AttackType.DamageType.disease ) && !ivch.IsImmortal() && !ivch.IsAffected(Affect.AFFECT_DISEASE) && MUDMath.NumberBits( 4 ) == 0 ) { ivch.SendText( "You feel hot and feverish.\r\n" ); SocketConnection.Act( "$n&n shivers and looks very ill.", ivch, null, null, SocketConnection.MessageTarget.room ); ivch.CombineAffect(plague); } } int dam = Math.Min( ch.Level, 5 ); ch.CurrentMana -= dam; ch.CurrentMoves -= dam; Combat.InflictSpellDamage( ch, ch, dam, "plague", AttackType.DamageType.disease ); } if( ( Database.SystemData.GameHour > 5 && Database.SystemData.GameHour < 21 ) && CharData.CheckSusceptible( ch, Race.DamageType.light ) ) { int dmg = 0; // Shouldn't this mess be a switch statement? if( ch.IsUnderground() ) { dmg = 0; } if( ch.InRoom.TerrainType == TerrainType.inside ) { dmg = 1; } else { if( ch.InRoom.TerrainType == TerrainType.forest || ch.InRoom.TerrainType == TerrainType.swamp ) { dmg = 2; } else { dmg = 4; } } if( Database.SystemData.WeatherData.Sky == Sysdata.SkyType.cloudy ) dmg /= 2; if (Database.SystemData.WeatherData.Sky == Sysdata.SkyType.rain) { dmg *= 3; dmg /= 4; } ch.SendText( "&+RThe heat of the sun feels terrible!&n\r\n" ); Combat.InflictSpellDamage( ch, ch, dmg, Spell.SpellList["poison"], AttackType.DamageType.light ); } if( ch.InRoom.TerrainType == TerrainType.underwater_has_ground && ( !ch.IsImmortal() && !ch.IsAffected( Affect.AFFECT_BREATHE_UNDERWATER ) && !CharData.CheckImmune( ch, Race.DamageType.drowning ) && !ch.HasInnate( Race.RACE_WATERBREATH ) ) ) { ch.SendText( "You can't breathe!\r\n" ); SocketConnection.Act( "$n&n sputters and chokes!", ch, null, null, SocketConnection.MessageTarget.room ); ch.Hitpoints -= 5; ch.UpdatePosition(); } else if( ch.InRoom.TerrainType != TerrainType.underwater_has_ground && ch.InRoom.TerrainType != TerrainType.unswimmable_water && ch.InRoom.TerrainType != TerrainType.swimmable_water && ch.HasInnate( Race.RACE_WATERBREATH ) && !Race.RaceList[ch.GetRace()].Name.Equals("Object", StringComparison.CurrentCultureIgnoreCase) && ch.GetRace() != Race.RACE_GOD ) { ch.SendText( "You can't breathe!\r\n" ); SocketConnection.Act( "$n&n sputters and gurgles!", ch, null, null, SocketConnection.MessageTarget.room ); ch.Hitpoints -= 5; ch.UpdatePosition(); } else if( ch.IsAffected( Affect.AFFECT_POISON ) ) { Combat.ApplyPoison(ch); } else { string text; if( ch.CurrentPosition == Position.incapacitated ) { text = String.Format( "char_update: {0}&n is incapacitated.", ch.Name ); ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, text ); if( ch.HasInnate( Race.RACE_REGENERATE ) && ch.Hitpoints < ch.GetMaxHit() ) { ++ch.Hitpoints; } else if( !ch.IsNPC() ) { Combat.InflictDamage(ch, ch, 1, String.Empty, ObjTemplate.WearLocation.none, AttackType.DamageType.none); } else if( MUDMath.NumberPercent() < 50 ) { ch.Hitpoints--; } } else if( ch.CurrentPosition == Position.mortally_wounded ) { text = String.Format( "char_update: {0}&n is mortally wounded.", ch.Name ); ImmortalChat.SendImmortalChat( null, ImmortalChat.IMMTALK_SPAM, 0, text ); if( ch.HasInnate( Race.RACE_REGENERATE ) && ch.Hitpoints < ch.GetMaxHit() ) { ++ch.Hitpoints; } else if( !ch.IsNPC() ) { Combat.InflictDamage(ch, ch, 2, String.Empty, ObjTemplate.WearLocation.none, AttackType.DamageType.none); } else { Combat.InflictDamage(ch, ch, 1, String.Empty, ObjTemplate.WearLocation.none, AttackType.DamageType.none); } } } ch.UpdatePosition(); // Refresh stoneskin on perm stone mobs. if( ch.IsNPC() && Macros.IsSet( ch.MobileTemplate.AffectedBy[ Affect.AFFECT_STONESKIN.Group ], Affect.AFFECT_STONESKIN.Vector ) && !ch.IsAffected( Affect.AFFECT_STONESKIN ) ) { ch.SetAffectBit( Affect.AFFECT_STONESKIN ); SocketConnection.Act( "$n&+L's skin turns to stone.&n", ch, null, null, SocketConnection.MessageTarget.room ); } // Thats all for mobs. if( ch.IsNPC() ) { continue; } if( ch.CurrentPosition == Position.dead ) { Combat.KillingBlow( ch, ch ); continue; } // Find player with oldest save time. if( ( !ch.Socket || ch.Socket.ConnectionStatus == SocketConnection.ConnectionState.playing ) && ch.Level >= 2 && ch.SaveTime < saveTime ) { chSave = ch; saveTime = ch.SaveTime; } if( ( ch.Level < Limits.LEVEL_AVATAR || ( !ch.Socket && !ch.IsSwitched ) ) ) { Object obj = Object.GetEquipmentOnCharacter( ch, ObjTemplate.WearLocation.hand_one ); if( ( obj ) && obj.ItemType == ObjTemplate.ObjectType.light && obj.Values[ 2 ] > 0 ) { if( --obj.Values[ 2 ] == 0 && ch.InRoom ) { --ch.InRoom.Light; SocketConnection.Act( "$p&n goes out.", ch, obj, null, SocketConnection.MessageTarget.room ); SocketConnection.Act( "$p&n goes out.", ch, obj, null, SocketConnection.MessageTarget.character ); obj.RemoveFromWorld(); } } if( ch.Timer > 15 && !ch.IsSwitched ) chQuit = ch; // This is so that hunger updates once every 16 CharacterUpdates, // This is so that thirst updates once every 16 CharacterUpdates, // This is so that drunkeness updates once every 2 CharacterUpdates, all at different intervals. if( ( _hunger % 2 ) == 1 ) { ch.AdjustDrunk( -1 ); } if( _hunger == 4 ) { ch.AdjustHunger(-1); } if( _hunger == 8 ) { ch.AdjustThirst(-1); } if (ch.IsAffected(Affect.AFFECT_THIRST)) { ch.AdjustThirst(-2); } if( ( ch.Hitpoints - ch.GetMaxHit() ) > 50 && ( _hunger % 5 == 0 ) ) { ch.Hitpoints--; } else if( ( ch.Hitpoints - ch.GetMaxHit() ) > 100 && ( _hunger % 4 == 0 ) ) { ch.Hitpoints--; } else if( ( ch.Hitpoints - ch.GetMaxHit() ) > 150 ) { ch.Hitpoints--; } } } // Autosave and autoquit. Check that these chars still exist. if( chSave || chQuit ) { foreach( CharData it in Database.CharList ) { ch = it; if( ch == chSave ) { CharData.SavePlayer( ch ); } if( ch == chQuit ) { CommandType.Interpret(ch, "camp"); } } } return; }