@Override public boolean invoke( MOB mob, List<String> commands, Physical givenTarget, boolean auto, int asLevel) { if (!mob.isInCombat()) { mob.tell(L("You must be in combat to do this!")); return false; } final MOB victim = super.getTarget(mob, commands, givenTarget); if (victim == null) return false; if (((victim == mob.getVictim()) && (mob.rangeToTarget() > 0)) || ((victim.getVictim() == mob) && (victim.rangeToTarget() > 0))) { mob.tell(L("You are too far away to disarm!")); return false; } if (mob.fetchWieldedItem() == null) { mob.tell(L("You need a weapon to disarm someone!")); return false; } Item hisWeapon = victim.fetchWieldedItem(); if (hisWeapon == null) hisWeapon = victim.fetchHeldItem(); if ((hisWeapon == null) || (!(hisWeapon instanceof Weapon)) || ((((Weapon) hisWeapon).weaponClassification() == Weapon.CLASS_NATURAL))) { mob.tell(L("@x1 is not wielding a weapon!", victim.charStats().HeShe())); return false; } if (!super.invoke(mob, commands, givenTarget, auto, asLevel)) return false; int levelDiff = victim.phyStats().level() - (mob.phyStats().level() + (2 * getXLEVELLevel(mob))); if (levelDiff > 0) levelDiff = levelDiff * 5; else levelDiff = 0; final boolean hit = (auto) || CMLib.combat().rollToHit(mob, victim); final boolean success = proficiencyCheck(mob, -levelDiff, auto) && (hit); if ((success) && ((hisWeapon.fitsOn(Wearable.WORN_WIELD)) || hisWeapon.fitsOn(Wearable.WORN_WIELD | Wearable.WORN_HELD))) { if (mob.location().show(mob, victim, this, CMMsg.MSG_NOISYMOVEMENT, null)) { final CMMsg msg = CMClass.getMsg(victim, hisWeapon, null, CMMsg.MSG_DROP, null); if (mob.location().okMessage(mob, msg)) { mob.location().send(victim, msg); mob.location() .show( mob, victim, CMMsg.MSG_NOISYMOVEMENT, auto ? L("<T-NAME> is disarmed!") : L("<S-NAME> disarm(s) <T-NAMESELF>!")); } } } else maliciousFizzle(mob, victim, L("<S-NAME> attempt(s) to disarm <T-NAMESELF> and fail(s)!")); return success; }
@Override public int castingQuality(MOB mob, Physical target) { if ((mob != null) && (target != null)) { final MOB victim = mob.getVictim(); if (victim == null) return Ability.QUALITY_INDIFFERENT; if (mob.isInCombat() && (mob.rangeToTarget() > 0)) return Ability.QUALITY_INDIFFERENT; if (mob.fetchWieldedItem() == null) return Ability.QUALITY_INDIFFERENT; Item hisWeapon = victim.fetchWieldedItem(); if (hisWeapon == null) hisWeapon = victim.fetchHeldItem(); if ((hisWeapon == null) || (!(hisWeapon instanceof Weapon)) || ((((Weapon) hisWeapon).weaponClassification() == Weapon.CLASS_NATURAL))) return Ability.QUALITY_INDIFFERENT; } return super.castingQuality(mob, target); }
@Override public boolean tick(Tickable ticking, int tickID) { if ((affected == null) || (!(affected instanceof Room))) return super.tick(ticking, tickID); if ((--damageTickDown) >= 0) return super.tick(ticking, tickID); damageTickDown = 4; HashSet H = null; if ((invoker() != null) && (invoker().location() == affected)) { H = new HashSet(); invoker().getGroupMembers(H); } final Room R = (Room) affected; for (int i = 0; i < R.numInhabitants(); i++) { final MOB M = R.fetchInhabitant(i); if ((M != null) && ((H == null) || (!H.contains(M)))) { if (invoker() != null) { final int harming = CMLib.dice().roll(1, adjustedLevel(invoker(), 0) / 3, 1); CMLib.combat() .postDamage( invoker(), M, this, harming, CMMsg.MASK_MALICIOUS | CMMsg.TYP_UNDEAD, Weapon.TYPE_BURSTING, L("The unholy aura <DAMAGE> <T-NAME>!")); } else { final int harming = CMLib.dice().roll(1, CMLib.ableMapper().lowestQualifyingLevel(ID()) / 3, 1); CMLib.combat() .postDamage( M, M, this, harming, CMMsg.MASK_MALICIOUS | CMMsg.TYP_UNDEAD, Weapon.TYPE_BURSTING, L("The unholy aura <DAMAGE> <T-NAME>!")); } if ((!M.isInCombat()) && (M.isMonster()) && (M != invoker) && (invoker != null) && (M.location() == invoker.location()) && (M.location().isInhabitant(invoker)) && (CMLib.flags().canBeSeenBy(invoker, M))) CMLib.combat().postAttack(M, invoker, M.fetchWieldedItem()); } } return super.tick(ticking, tickID); }
public void tickLycanthropically(MOB mob) { if (mob == null) return; if (mob.location() == null) return; if (mob.isInCombat()) return; if ((CMLib.dice().rollPercentage() < 15) && ((mob.location().domainType() & Room.INDOORS) > 0)) mob.location() .show(mob, null, CMMsg.MSG_NOISE, L("<S-NAME> howl(s) at the moon! ARROOOOOOOO!!!!")); // time to tick lycanthropically final MOB M = victimHere(mob.location(), mob); if (M != null) { deathTrail = null; CMLib.combat().postAttack(mob, M, mob.fetchWieldedItem()); return; } if ((deathTrail != null) && (!deathTrail.contains(mob.location()))) deathTrail = null; if (deathTrail == null) { final Vector rooms = new Vector(); if ((findVictim(mob, mob.location(), rooms, 0)) && (rooms.size() > 0)) { TrackingLibrary.TrackingFlags flags; flags = new TrackingLibrary.TrackingFlags() .plus(TrackingLibrary.TrackingFlag.OPENONLY) .plus(TrackingLibrary.TrackingFlag.AREAONLY) .plus(TrackingLibrary.TrackingFlag.NOEMPTYGRIDS) .plus(TrackingLibrary.TrackingFlag.NOAIR) .plus(TrackingLibrary.TrackingFlag.NOWATER); deathTrail = CMLib.tracking().findBastardTheBestWay(mob.location(), rooms, flags, 50); if (deathTrail != null) deathTrail.add(mob.location()); } } if (deathTrail != null) { final int nextDirection = CMLib.tracking().trackNextDirectionFromHere(deathTrail, mob.location(), true); if ((nextDirection == 999) || (nextDirection == -1)) deathTrail = null; else if (nextDirection >= 0) { final Room nextRoom = mob.location().getRoomInDir(nextDirection); if ((nextRoom != null) && ((nextRoom.getArea() == mob.location().getArea())) || (!mob.isMonster())) { if (!CMLib.tracking().walk(mob, nextDirection, false, false)) deathTrail = null; else if (CMLib.dice().rollPercentage() < 15) mob.location().show(mob, null, CMMsg.MSG_NOISE, L("<S-NAME> sniff(s) at the air.")); } else deathTrail = null; } } }
@Override public int castingQuality(MOB mob, Physical target) { if ((mob != null) && (target != null) && (target instanceof MOB)) { final Race R = ((MOB) target).charStats().getMyRace(); if (R.bodyMask()[Race.BODY_HEAD] <= 0) return Ability.QUALITY_INDIFFERENT; LegalBehavior B = null; if (mob.location() != null) B = CMLib.law().getLegalBehavior(mob.location()); List<LegalWarrant> warrants = new Vector<LegalWarrant>(); if (B != null) warrants = B.getWarrantsOf(CMLib.law().getLegalObject(mob.location()), (MOB) target); if (warrants.size() == 0) return Ability.QUALITY_INDIFFERENT; final Item w = mob.fetchWieldedItem(); Weapon ww = null; if ((w == null) || (!(w instanceof Weapon))) return Ability.QUALITY_INDIFFERENT; ww = (Weapon) w; if (ww.weaponDamageType() != Weapon.TYPE_SLASHING) return Ability.QUALITY_INDIFFERENT; if (mob.isInCombat() && (mob.rangeToTarget() > 0)) return Ability.QUALITY_INDIFFERENT; if (!CMLib.flags().isBoundOrHeld(target)) return Ability.QUALITY_INDIFFERENT; } return super.castingQuality(mob, target); }
@Override public void spring(MOB mob) { final Room room = mob.location(); if (room != null) { final Set<MOB> friendlySet = new HashSet<MOB>(); if (invoker() != null) invoker().getGroupMembers(friendlySet); room.show( mob, affected, CMMsg.MSG_OK_ACTION, L("<T-NAME> explodes, spraying clumps of stomach acid everywhere!")); for (final Enumeration<MOB> m = room.inhabitants(); m.hasMoreElements(); ) { MOB M = m.nextElement(); if ((M != null) && (!friendlySet.contains(M))) { final MOB invoker = (invoker() != null) ? invoker() : M; final int damage = CMLib.dice().roll(4, 5 + invoker.phyStats().level(), 0); CMLib.combat() .postDamage( invoker, M, this, damage, CMMsg.MASK_MALICIOUS | CMMsg.MASK_ALWAYS | CMMsg.TYP_ACID, Weapon.TYPE_MELTING, L("The acid clumps <DAMAGE> <T-NAME>!")); if ((!M.isInCombat()) && (M.isMonster()) && (M != invoker) && (M.location() == invoker.location()) && (M.location().isInhabitant(invoker)) && (CMLib.flags().canBeSeenBy(invoker, M))) CMLib.combat().postAttack(M, invoker, M.fetchWieldedItem()); } } } Physical affected = this.affected; unInvoke(); if (affected instanceof Item) ((Item) affected).destroy(); }
@Override public boolean invoke( MOB mob, List<String> commands, Physical givenTarget, boolean auto, int asLevel) { final MOB target = super.getTarget(mob, commands, givenTarget); if (target == null) return false; final Race R = target.charStats().getMyRace(); if (R.bodyMask()[Race.BODY_HEAD] <= 0) { mob.tell(L("@x1 has no head!", target.name(mob))); return false; } LegalBehavior B = null; if (mob.location() != null) B = CMLib.law().getLegalBehavior(mob.location()); List<LegalWarrant> warrants = new Vector<LegalWarrant>(); if (B != null) warrants = B.getWarrantsOf(CMLib.law().getLegalObject(mob.location()), target); if ((warrants.size() == 0) && (!CMSecurity.isAllowed(mob, mob.location(), CMSecurity.SecFlag.ABOVELAW))) { mob.tell(L("You are not allowed to behead @x1 at this time.", target.Name())); return false; } final Item w = mob.fetchWieldedItem(); Weapon ww = null; if ((w == null) || (!(w instanceof Weapon))) { mob.tell(L("You cannot behead without a weapon!")); return false; } ww = (Weapon) w; if ((!auto) && (!CMSecurity.isASysOp(mob))) { if (ww.weaponDamageType() != Weapon.TYPE_SLASHING) { mob.tell(L("You cannot behead with a @x1!", ww.name())); return false; } if (mob.isInCombat() && (mob.rangeToTarget() > 0)) { mob.tell(L("You are too far away to try that!")); return false; } if (!CMLib.flags().isBoundOrHeld(target)) { mob.tell(L("@x1 is not bound and would resist.", target.charStats().HeShe())); return false; } } if (!super.invoke(mob, commands, givenTarget, auto, asLevel)) return false; int levelDiff = target.phyStats().level() - (mob.phyStats().level() + (2 * getXLEVELLevel(mob))); if (levelDiff > 0) levelDiff = levelDiff * 3; else levelDiff = 0; final boolean hit = (auto) || CMLib.combat().rollToHit(mob, target); boolean success = proficiencyCheck(mob, 0, auto) && (hit); if (success) { final CMMsg msg = CMClass.getMsg( mob, target, this, CMMsg.MASK_MALICIOUS | CMMsg.MASK_MOVE | CMMsg.MASK_SOUND | CMMsg.TYP_JUSTICE | (auto ? CMMsg.MASK_ALWAYS : 0), null); if (mob.location().okMessage(mob, msg)) { mob.location().send(mob, msg); target.curState().setHitPoints(1); final Ability A2 = target.fetchEffect("Injury"); if (A2 != null) A2.setMiscText(mob.Name() + "/head"); CMLib.combat() .postDamage( mob, target, ww, Integer.MAX_VALUE / 2, CMMsg.MSG_WEAPONATTACK, ww.weaponClassification(), auto ? "" : L( "^F^<FIGHT^><S-NAME> rear(s) back and behead(s) <T-NAME>!^</FIGHT^>^?@x1", CMLib.protocol().msp("decap.wav", 30))); mob.location().recoverRoomStats(); final Item limb = CMClass.getItem("GenLimb"); limb.setName(L("@x1`s head", target.Name())); limb.basePhyStats().setAbility(1); limb.setDisplayText(L("the bloody head of @x1 is sitting here.", target.Name())); limb.setSecretIdentity(target.name() + "`s bloody head."); int material = RawMaterial.RESOURCE_MEAT; for (int r = 0; r < R.myResources().size(); r++) { final Item I = R.myResources().get(r); final int mat = I.material() & RawMaterial.MATERIAL_MASK; if (((mat == RawMaterial.MATERIAL_FLESH)) || (r == R.myResources().size() - 1)) { material = I.material(); break; } } limb.setMaterial(material); limb.basePhyStats().setLevel(1); limb.basePhyStats().setWeight(5); limb.recoverPhyStats(); mob.location().addItem(limb, ItemPossessor.Expire.Player_Drop); for (int i = 0; i < warrants.size(); i++) { final LegalWarrant W = warrants.get(i); W.setCrime("pardoned"); W.setOffenses(0); } } else success = false; if (mob.getVictim() == target) mob.makePeace(true); if (target.getVictim() == mob) target.makePeace(true); } else maliciousFizzle(mob, target, L("<S-NAME> attempt(s) a beheading and fail(s)!")); return success; }