/// <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> /// 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> /// See if an theft justifies a THEFT crime entry. /// /// This requires that the person be in justice and that there /// be a mob flagged witness present /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void CheckThief( CharData ch, CharData victim ) { // Check for justice if (ch == null || victim == null) { return; } if (ch.InRoom.Area.JusticeType == 0) { return; } // NPC's are fair game. if (victim.IsNPC()) { return; } // NPC's are cool of course // Hitting yourself is cool too (bleeding). // Hitting immortals are fine. if (ch.IsNPC() || ch == victim || victim.Level > Limits.LEVEL_HERO) { return; } // Vampires and the living dead are fair game. if (victim.IsUndead()) { return; } foreach( CharData roomChar in ch.InRoom.People ) { if( roomChar.IsNPC() && roomChar.HasActionBit(MobTemplate.ACT_WITNESS ) ) { // Crime committed and witnessed by an NPC, add a crime data CreateCrime( ch, victim, CRIME_THEFT ); Save(); return; } // Crime witnessed by player, give them the chance to report it return; } return; }
/// <summary> /// Checks whether the mob should leave a corpse when it dies. If so, returns /// true. Otherwise, it prints a message, if appropriate, and returns false. /// </summary> /// <param name="ch"></param> /// <returns></returns> static bool LeavesNoCorpse( CharData ch ) { string msg = String.Empty; bool noCorpse = false; if( ch.IsUndead() ) { noCorpse = true; msg = String.Format( "$n&N crumbles to dust." ); } else if( ch.IsElemental() ) { noCorpse = true; msg = String.Format( "$n&n returns to the elements from which it formed." ); } if( noCorpse ) { SocketConnection.Act( msg, ch, null, null, SocketConnection.MessageTarget.room ); if( ch.GetCash() > 0 ) { Object coins = Object.CreateMoney( ch.GetCopper(), ch.GetSilver(), ch.GetGold(), ch.GetPlatinum() ); coins.AddToRoom( ch.InRoom ); } for( int i = (ch.Carrying.Count-1); i >= 0; i-- ) { Object obj = ch.Carrying[i]; obj.RemoveFromChar(); obj.AddToRoom( ch.InRoom ); } } return noCorpse; }
/// <summary> /// Checks whether an attack justifies an attempted murder crime entry. /// /// This requires that the victim be in justice and that there be a mob /// flagged with the ACT_WITNESS flag in the room. /// </summary> /// <param name="ch"></param> /// <param name="victim"></param> public static void CheckAttemptedMurder( CharData ch, CharData victim ) { // Make sure input is valid. if( ch == null || victim == null ) return; // Check for justice. Suicide is ok. Make sure areas are there. if( ch.InRoom == null || ch.InRoom.Area == null || ch.InRoom.Area.JusticeType == 0 ) return; // NPC's are fair game. if( victim.IsNPC() ) return; // NPC's are cool of course // Hitting yourself is cool too (bleeding). // Hitting immortals are fine. if (ch.IsNPC() || ch == victim || victim.Level > Limits.LEVEL_HERO) { return; } // Vampires and the living dead are fair game. if (victim.IsUndead()) { return; } // Defending yourself once you're already attacked is okay. if (victim.Fighting != null && victim.Fighting == ch) { return; } foreach( CharData roomChar in ch.InRoom.People ) { if( roomChar.IsNPC() && roomChar.HasActionBit( MobTemplate.ACT_WITNESS ) ) { // Crime committed and witnessed by a mob, add a crime data CreateCrime( ch, victim, CRIME_ATT_MURDER ); Save(); return; } // Crime witnessed by player, give them the chance to report it return; } return; }