package com.planet_ink.coffee_mud.Abilities.Properties; import com.planet_ink.coffee_mud.Libraries.interfaces.*; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.*; import com.planet_ink.coffee_mud.core.collections.*; import com.planet_ink.coffee_mud.Abilities.interfaces.*; import com.planet_ink.coffee_mud.Areas.interfaces.*; import com.planet_ink.coffee_mud.Behaviors.interfaces.*; import com.planet_ink.coffee_mud.CharClasses.interfaces.*; import com.planet_ink.coffee_mud.Commands.interfaces.*; import com.planet_ink.coffee_mud.Common.interfaces.*; import com.planet_ink.coffee_mud.Exits.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.*; import com.planet_ink.coffee_mud.Locales.interfaces.*; import com.planet_ink.coffee_mud.MOBS.interfaces.*; import com.planet_ink.coffee_mud.Races.interfaces.*; import java.util.*; /** * * Title: False Realities Flavored CoffeeMUD * Description: The False Realities Version of CoffeeMUD * Copyright: Copyright (c) 2003 Jeremy Vyska * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * Company: http://www.falserealities.com * * * @author FR - Jeremy Vyska; CM - Bo Zimmerman * @version 1.0.0.0 */ public class Prop_ClanEquipment extends Property implements TriggeredAffect { @Override public String ID() { return "Prop_ClanEquipment"; } @Override public String name() { return "Clan Equipment"; } @Override public boolean bubbleAffect() { return true; } @Override public long flags() { return Ability.FLAG_CASTER; } @Override protected int canAffectCode() { return Ability.CAN_ITEMS; } protected boolean activated = false; protected String type = ""; protected int TypeOfEffect = 0; protected int WeaponType = 0; protected int PowerLevel = 0; protected long LastChecked = 0; protected boolean notAgain = false; protected String clanName = ""; protected String clanType = ""; String lastMessage = null; protected CharStats EQadjCharStats = null; protected String secretWord = CMProps.getAnyListFileValue(CMProps.ListFile.MAGIC_WORDS); @Override public int triggerMask() { if(affected instanceof Weapon) return TriggeredAffect.TRIGGER_HITTING_WITH; if(affected instanceof Armor) return TriggeredAffect.TRIGGER_BEING_HIT; return TriggeredAffect.TRIGGER_USE; } @Override public String accountForYourself() { // My slightly complicated way of showing the clan effect when ID'd final StringBuffer id=new StringBuffer(L("@x1 @x2 Bonus: ",clanType,clanName)); if((affected instanceof Weapon)&&(!(affected instanceof Wand))&&(TypeOfEffect<1000)) { id.append("Does "+(1*PowerLevel)+"-"+(6*PowerLevel)+" additional "+type.toLowerCase()+" damage."); } else if((affected instanceof Armor)&&(TypeOfEffect<1000)&&(!(affected instanceof Shield))) { id.append("Raises "+type.toLowerCase()+" resistance by "+(PowerLevel*5)+"."); } if((affected instanceof Armor)&&(TypeOfEffect<1000)&&(affected instanceof Shield)) { id.append("Causes "+(1*PowerLevel)+"-"+(3*PowerLevel)+" "+type.toLowerCase()+" damage to melee attackers."); } if((affected instanceof Wand)&&(TypeOfEffect<1000)) { id.append("Does "+(1*PowerLevel)+"-"+(6*PowerLevel)+" "+type.toLowerCase()+" damage when the user says `"+secretWord+"` to the target."); } return id.toString(); } @Override public void setMiscText(String text) { super.setMiscText(text); final Vector<String> V=CMParms.parse(text); if(V.size()<4) { return; } type=V.elementAt(0); PowerLevel=Integer.valueOf(V.elementAt(1)).intValue(); clanName=V.elementAt(2); clanType=V.elementAt(3); secretWord=getWandWord(text); // try to randomize the spell word a // little // Armor this.EQadjCharStats=(CharStats)CMClass.getCommon("DefaultCharStats"); initAdjustments(EQadjCharStats); if(type.equalsIgnoreCase("PARALYSIS")) { TypeOfEffect=CMMsg.TYP_PARALYZE; WeaponType=Weapon.TYPE_STRIKING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_PARALYSIS,PowerLevel*5); } else if(type.equalsIgnoreCase("FIRE")) { TypeOfEffect=CMMsg.TYP_FIRE; WeaponType=Weapon.TYPE_BURNING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_FIRE,PowerLevel*5); } else if(type.equalsIgnoreCase("COLD")) { TypeOfEffect=CMMsg.TYP_COLD; WeaponType=Weapon.TYPE_FROSTING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_COLD,PowerLevel*5); } else if(type.equalsIgnoreCase("WATER")) { TypeOfEffect=CMMsg.TYP_WATER; WeaponType=Weapon.TYPE_SLASHING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_WATER,PowerLevel*5); } else if(type.equalsIgnoreCase("GAS")) { TypeOfEffect=CMMsg.TYP_GAS; WeaponType=Weapon.TYPE_GASSING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_GAS,PowerLevel*5); } else if(type.equalsIgnoreCase("MIND")) { TypeOfEffect=CMMsg.TYP_MIND; WeaponType=Weapon.TYPE_STRIKING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_MIND,PowerLevel*5); } else if(type.equalsIgnoreCase("ACID")) { TypeOfEffect=CMMsg.TYP_ACID; WeaponType=Weapon.TYPE_MELTING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_ACID,PowerLevel*5); } else if(type.equalsIgnoreCase("ELECTRIC")) { TypeOfEffect=CMMsg.TYP_ELECTRIC; WeaponType=Weapon.TYPE_BURNING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_ELECTRIC,PowerLevel*5); } else if(type.equalsIgnoreCase("POISON")) { TypeOfEffect=CMMsg.TYP_POISON; WeaponType=Weapon.TYPE_STRIKING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_POISON,PowerLevel*5); } else if(type.equalsIgnoreCase("DISEASE")) { TypeOfEffect=CMMsg.TYP_DISEASE; WeaponType=Weapon.TYPE_STRIKING; this.EQadjCharStats.setStat(CharStats.STAT_SAVE_DISEASE,PowerLevel*5); } else if(type.equalsIgnoreCase("HEALTH")) { TypeOfEffect=1001; WeaponType=Weapon.TYPE_BURSTING; } else if(type.equalsIgnoreCase("MAGIC")) { TypeOfEffect=1002; WeaponType=Weapon.TYPE_BURSTING; } else if(type.equalsIgnoreCase("SPEED")) { TypeOfEffect=1003; } } public boolean useAsWand(MOB mob, int level) { int manaRequired=50; // For simplicity, there's no charges BUT use costs a flat 10% mana manaRequired=(int)CMath.div(mob.maxState().getMana(),10); manaRequired-=(5*level); if(manaRequired<5) manaRequired=5; if(manaRequired>mob.curState().getMana()) { mob.tell(L("You don't have enough mana.")); return false; } mob.curState().adjMana(-manaRequired,mob.maxState()); return true; } public static String getWandWord(String from) { int hash=from.hashCode(); if(hash<0) { hash=hash*-1; } return CMProps.getListFileChoiceFromIndexedListByHash(CMProps.ListFile.MAGIC_WORDS,hash); } public boolean checkWave(MOB mob, String message, Wand me) { if((mob.isMine(me))&&(!me.amWearingAt(Wearable.IN_INVENTORY))) { final int x=message.toUpperCase().indexOf(secretWord.toUpperCase()); return (x>=0); } return false; } /* * ********************** Staff/Wand Clan Eq ********************** */ public void waveIfAble(MOB mob, Environmental afftarget, String message, Wand me) { if((mob.isMine(me))&&(afftarget!=null)&&(afftarget instanceof MOB)&&(!me.amWearingAt(Wearable.IN_INVENTORY))) { MOB target=null; if((mob.location()!=null)) { target=(MOB)afftarget; } final int x=message.toUpperCase().indexOf(secretWord.toUpperCase()); if(x>=0) { message=message.substring(x+secretWord.length()); final int y=message.indexOf('\''); if(y>=0) { message=message.substring(0,y); } message=message.trim(); final Ability wandUse=mob.fetchAbility("Skill_WandUse"); if((wandUse==null)||(!wandUse.proficiencyCheck(mob,0,false))) { mob.tell(L("@x1 glows faintly for a moment, then fades.",me.name())); } else { wandUse.setInvoker(mob); if(useAsWand(mob,wandUse.abilityCode())) { mob.location().show(mob,null,CMMsg.MSG_OK_VISUAL,L("@x1 glows brightly.",me.name())); final int flameDamage=CMLib.dice().roll(1,6*PowerLevel,1*PowerLevel); CMLib.combat().postDamage(mob,target,null,flameDamage,CMMsg.MASK_MALICIOUS|CMMsg.MASK_ALWAYS|TypeOfEffect,WeaponType, L("^F^<FIGHT^>The magic of @x1 <DAMAGE> <T-NAME>!^</FIGHT^>^?",clanName)); wandUse.helpProficiency(mob, 0); return; } } } } } public static void initAdjustments(CharStats adjCharStats) { // ensure we get no NULL errors for(final int i : CharStats.CODES.SAVING_THROWS()) adjCharStats.setStat(i,0); } @Override public void affectCharStats(MOB affectedMOB, CharStats affectedStats) { if(EQadjCharStats==null) { setMiscText(text()); /* * ************************* Armor-based Resistances * ************************* */ } if((affected!=null)&&(affected instanceof Armor)&&(!(affected instanceof Shield))&&(activated) &&(!((Armor)affected).amWearingAt(Wearable.IN_INVENTORY))) { for(final int i : CharStats.CODES.SAVING_THROWS()) affectedStats.setStat(i,affectedStats.getStat(i)+EQadjCharStats.getStat(i)); } super.affectCharStats(affectedMOB,affectedStats); } @Override public void executeMsg(final Environmental myHost, final CMMsg msg) { super.executeMsg(myHost,msg); if(((System.currentTimeMillis()-LastChecked)>TimeManager.MILI_HOUR)&&(affected!=null)) { if((clanName!=null)&&(clanName.length()>0)&&(CMLib.clans().getClan(clanName)==null)) affected.delEffect(this); LastChecked=System.currentTimeMillis(); } MOB mob=null; MOB source=null; if((affected!=null)&&(affected instanceof Item)) { if((((Item)affected).owner()!=null)&&((Item)affected).owner() instanceof MOB) { mob=(MOB)((Item)affected).owner(); } } // if held by the wrong clan, it is inactive. if((mob!=null)&&(mob.getClanRole(clanName)!=null)) activated=true; else activated=false; if(!activated) return; source=msg.source(); /* * ********************** Weapon addtl. Damage * ********************** */ if((msg.source().location()!=null)&&(msg.targetMinor()==CMMsg.TYP_DAMAGE)&&(msg.value()>0)&&(msg.tool()==affected)&&(!notAgain) &&(msg.target() instanceof MOB)&&(msg.tool() instanceof Weapon)&&(!(msg.tool() instanceof Wand))&&(TypeOfEffect<1000) &&(!((MOB)msg.target()).amDead())) { final double flameDamage=CMLib.dice().roll(1,6*PowerLevel,1*PowerLevel); final String str=L("^F^<FIGHT^>The magic of @x1 <DAMAGE> <T-NAME>!^</FIGHT^>^?",clanName); CMLib.combat().postDamage(msg.source(),(MOB)msg.target(),null,(int)Math.round(flameDamage), CMMsg.MASK_MALICIOUS|CMMsg.MASK_ALWAYS|TypeOfEffect,WeaponType,str); } /* * ********************** Shield Thorns Damage ********************** */ if((mob!=null)&&(msg.amITarget(mob))&&(affected instanceof Shield)&&(!((Shield)affected).amWearingAt(Wearable.IN_INVENTORY)) &&(TypeOfEffect<1000)&&(!msg.amISource(mob))) { if((CMLib.dice().rollPercentage()>32+msg.source().charStats().getStat(CharStats.STAT_DEXTERITY)) &&(msg.source().rangeToTarget()==0) &&((lastMessage==null)||(lastMessage.indexOf("The magic around")<0)) &&((msg.targetMajor(CMMsg.MASK_HANDS))||(msg.targetMajor(CMMsg.MASK_MOVE)))) { final CMMsg msg2=CMClass.getMsg(mob,source,this,CMMsg.MSG_CAST_ATTACK_VERBAL_SPELL,null); if((source!=null)&&(source.location().okMessage(source,msg2))) { source.location().send(source,msg2); if(msg2.value()<=0) { final int damage=CMLib.dice().roll(1,3*PowerLevel,1*PowerLevel); CMLib.combat().postDamage(mob,source,this,damage,CMMsg.MASK_MALICIOUS|CMMsg.MASK_ALWAYS|TypeOfEffect,WeaponType, L("^F^<FIGHT^>The magic of @x1 around <S-NAME> <DAMAGE> <T-NAME>!^</FIGHT^>^?",clanName)); if((!source.isInCombat())&&(source.isMonster())&&(source!=mob)&&(source.location()==mob.location())&&(source.location().isInhabitant(mob))&&(CMLib.flags().canBeSeenBy(mob,source))) CMLib.combat().postAttack(source,mob,source.fetchWieldedItem()); } } } } /* * ************************* Staff/Wand Message Watch * ************************* */ if(affected instanceof Wand) { switch(msg.targetMinor()) { case CMMsg.TYP_WAND_USE: if(msg.amITarget(this)&&((msg.tool()==null)||(msg.tool() instanceof Physical))) waveIfAble(mob,msg.tool(),msg.targetMessage(),(Wand)affected); break; case CMMsg.TYP_SPEAK: if(msg.sourceMinor()==CMMsg.TYP_SPEAK) { boolean alreadyWanding=false; final List<CMMsg> trailers =msg.trailerMsgs(); if(trailers!=null) { for(final CMMsg msg2 : trailers) { if((msg2.targetMinor()==CMMsg.TYP_WAND_USE) &&(msg2.target() == this)) alreadyWanding=true; } } final String said=CMStrings.getSayFromMessage(msg.sourceMessage()); if((!alreadyWanding) &&(said != null) &&(checkWave(mob,said,(Wand)affected))) msg.addTrailerMsg(CMClass.getMsg(msg.source(),this,msg.target(),CMMsg.NO_EFFECT,null,CMMsg.MASK_ALWAYS|CMMsg.TYP_WAND_USE,said,CMMsg.NO_EFFECT,null)); } break; default: break; } } } }