/********************************************************************** * Title: dot.scriptlib * Description: contains the library methods for damage over time effects **********************************************************************/ /***** INCLUDES ********************************************************/ include library.prose; include library.vehicle; include library.utils; include library.combat; include library.ai_lib; include java.util.Enumeration; include java.util.HashSet; include java.util.Vector; include library.colors; include library.beast_lib; include library.skill; include library.trial; /***** CONSTANTS *******************************************************/ // Dot types const string DOT_BLEEDING = "bleeding"; const string DOT_POISON = "poison"; const string DOT_DISEASE = "disease"; const string DOT_FIRE = "fire"; const string DOT_ACID = "acid"; const string DOT_ENERGY = "energy"; const string DOT_COLD = "cold"; const string DOT_ELECTRICITY = "electricity"; const string DOT_KINETIC = "kinetic"; // Scripts const string SCRIPT_PLAYER_DOT = "player.player_dot"; // Dot ScriptVars const string VAR_DOT = "dot"; const string VAR_DOT_ROOT = "dot."; const string VAR_TYPE = ".type"; const string VAR_ATTRIBUTE = ".attribute"; const string VAR_POTENCY = ".potency"; // source only const string VAR_STRENGTH = ".strength"; const string VAR_DURATION = ".duration"; const string VAR_TIME_START = ".time_start"; const string VAR_LAST_PULSE = ".last_pulse"; const string VAR_HANDLER = ".handler"; const string VAR_ATTACKER = ".attacker"; const string VAR_USES = ".uses"; // source only // System constants const int DOT_MAXIMUM_COUNT = 3; const int BASE_RESISTANCE = 100; const int BLEEDING_PULSE = 1; const int POISON_PULSE = 1; const int DISEASE_PULSE = 1; const int FIRE_PULSE = 1; const int ACID_PULSE = 1; const int ENERGY_PULSE = 1; const int DOT_GRACE_PERIOD = 60; const int MOD_DIVISOR = 3; const int DOT_ARMOR_MITIGATION_PERCENT = 50; const float VAR_EFFECT_DISPLAY_RADIUS = 45.0f; // Script Vars const string SCRIPT_VAR_DOT_GRACE = "dot.dot_grace"; // Hit locations const string[] HIT_LOCATIONS = {"body", "head", "right_arm", "left_arm", "right_leg", "left_leg"}; // Attribute hit location const int[] HIT_LOCATION_ATTRIBUTE = {HEALTH, MIND, HEALTH, HEALTH, ACTION, ACTION}; // String id's const string_id SID_BLEEDING = new string_id("dot_message", "start_bleeding"); const string_id SID_POISONED = new string_id("dot_message", "start_poisoned"); const string_id SID_DISEASED = new string_id("dot_message", "start_diseased"); const string_id SID_FIRE = new string_id("dot_message", "start_fire"); const string_id SID_ACID = new string_id("dot_message", "start_acid"); const string_id SID_ENERGY = new string_id("dot_message", "start_energy"); const string_id SID_COLD = new string_id("dot_message", "start_cold"); const string_id SID_ELECTRICITY = new string_id("dot_message", "start_electricity"); const string_id SID_KINETIC = new string_id("dot_message", "start_kinetic"); const string_id SID_BLEEDING_INCREASE = new string_id("dot_message", "increase_bleeding"); const string_id SID_POISONED_INCREASE = new string_id("dot_message", "increase_poisoned"); const string_id SID_DISEASED_INCREASE = new string_id("dot_message", "increase_diseased"); const string_id SID_FIRE_INCREASE = new string_id("dot_message", "increase_fire"); const string_id SID_ACID_INCREASE = new string_id("dot_message", "increase_acid"); const string_id SID_ENERGY_INCREASE = new string_id("dot_message", "increase_energy"); const string_id SID_COLD_INCREASE = new string_id("dot_message", "increase_cold"); const string_id SID_ELECTRICITY_INCREASE = new string_id("dot_message", "increase_electricity"); const string_id SID_KINETIC_INCREASE = new string_id("dot_message", "increase_kinetic"); const string_id SID_BLEEDING_DECREASE = new string_id("dot_message", "decrease_bleeding"); const string_id SID_POISONED_DECREASE = new string_id("dot_message", "decrease_poisoned"); const string_id SID_DISEASED_DECREASE = new string_id("dot_message", "decrease_diseased"); const string_id SID_FIRE_DECREASE = new string_id("dot_message", "decrease_fire"); const string_id SID_ACID_DECREASE = new string_id("dot_message", "decrease_acid"); const string_id SID_ENERGY_DECREASE = new string_id("dot_message", "decrease_energy"); const string_id SID_COLD_DECREASE = new string_id("dot_message", "decrease_cold"); const string_id SID_ELECTRICITY_DECREASE = new string_id("dot_message", "decrease_electricity"); const string_id SID_KINETIC_DECREASE = new string_id("dot_message", "decrease_kinetic"); const string_id SID_BLEEDING_STOP = new string_id("dot_message", "stop_bleeding"); const string_id SID_POISONED_STOP = new string_id("dot_message", "stop_poisoned"); const string_id SID_DISEASED_STOP = new string_id("dot_message", "stop_diseased"); const string_id SID_FIRE_STOP = new string_id("dot_message", "stop_fire"); const string_id SID_ACID_STOP = new string_id("dot_message", "stop_acid"); const string_id SID_ENERGY_STOP = new string_id("dot_message", "stop_energy"); const string_id SID_COLD_STOP = new string_id("dot_message", "stop_cold"); const string_id SID_ELECTRICITY_STOP = new string_id("dot_message", "stop_electricity"); const string_id SID_KINETIC_STOP = new string_id("dot_message", "stop_kinetic"); const string_id SID_DOT_RESISTED = new string_id("dot_message", "dot_resisted"); const string_id SID_DOT_RESISTED_SPAM = new string_id("dot_message", "spam_dot_resisted"); const string_id SID_BLEED_DMG = new string_id("dot_message", "bleed_dmg"); const string_id SID_BLEED_DMG_ATKR = new string_id("dot_message", "bleed_dmg_atkr"); const string_id SID_POISON_DMG = new string_id("dot_message", "poison_dmg"); const string_id SID_POISON_DMG_ATKR = new string_id("dot_message", "poison_dmg_atkr"); const string_id SID_FIRE_DMG = new string_id("dot_message", "fire_dmg"); const string_id SID_FIRE_DMG_ATKR = new string_id("dot_message", "fire_dmg_atkr"); const string_id SID_DISEASE_DMG = new string_id("dot_message", "disease_dmg"); const string_id SID_DISEASE_DMG_ATKR = new string_id("dot_message", "disease_dmg_atkr"); const string_id SID_ACID_DMG = new string_id("dot_message", "acid_dmg"); const string_id SID_ACID_DMG_ATKR = new string_id("dot_message", "acid_dmg_atkr"); const string_id SID_ENERGY_DMG = new string_id("dot_message", "energy_dmg"); const string_id SID_ENERGY_DMG_ATKR = new string_id("dot_message", "energy_dmg_atkr"); const string_id SID_COLD_DMG = new string_id("dot_message", "cold_dmg"); const string_id SID_COLD_DMG_ATKR = new string_id("dot_message", "cold_dmg_atkr"); const string_id SID_ELECTRICITY_DMG = new string_id("dot_message", "electricity_dmg"); const string_id SID_ELECTRICITY_DMG_ATKR = new string_id("dot_message", "electricity_dmg_atkr"); const string_id SID_KINETIC_DMG = new string_id("dot_message", "kinetic_dmg"); const string_id SID_KINETIC_DMG_ATKR = new string_id("dot_message", "kinetic_dmg_atkr"); /***** TRIGGERS ********************************************************/ /***** MESSAGEHANDLERS *************************************************/ /***** COMMANDHANDLERS *************************************************/ /***** FUNCTIONS *******************************************************/ /*********************************************************************** * @brief Attempts to place a damage over time effect on the specified * target. * * @param obj_id target * @param string type dot type (poison, bleeding, etc.) * @param string dot_id a marker enabling a script to find a specific dot. * No target may have two or more dots with the same dot_id. * @param int attribute Attribute to apply dot * @param int potency a modifier to the chance to resist. Potency -1 can't be resisted * @param int strength the amount of damage inflicted per pulse * @param int duration the time before the dot dissipates. -1 duration * dots do not dissipate * @param boolean verbose whether or not to give messaging * * @return boolean true on success. False on error or resist. ***********************************************************************/ boolean applyDotEffect(obj_id target, obj_id attacker, string type, string dot_id, int attribute, int potency, int strength, int duration, boolean verbose, string handler) { if(!isIdValid(attacker)) { attacker = getSelf(); if(!isIdValid(attacker)) { return false; } } else { if (!isMob(target)) return false; } if (type == null) return false; if (dot_id == null) return false; if (attribute < 0 || attribute > 8) return false; if (potency != -1 && potency < 1) return false; if (strength < 1) return false; if (duration < 1) return false; if (!canApplyDotType(target, type)) return false; if(isIdValid(attacker) && isMob(attacker)) { addHate(target, attacker, 0.0f); addHate(attacker, target, 0.0f); } // Check for resistance. Potency of -1 cannot be resisted. if (potency != - 1) { if (attemptDotResist(target, type, potency, true)) return false; } // Keep track of whether or not this dot is to stack on an existing one. boolean stacking = false; // Keep track of whether or not the player has already has a dot of this type. boolean new_dot_type = false; string[] dot_types = getAllDotsType(target, type); if (dot_types == null) new_dot_type = true; // Check for a dot of the same id. A target can only have one dot of the same id if (hasDotId(target, dot_id)) { // The current dot is replaced if the old dot is of lesser strength. int old_strength = getDotStrength(target, dot_id); if (old_strength >= strength) return false; else stacking = true; } float expertiseDotIncrease = getEnhancedSkillStatisticModifierUncapped(attacker, "expertise_dot_increase"); if(expertiseDotIncrease > 0.0f) { // int strold = strength; strength += (int)((float)strength * (expertiseDotIncrease / 100.0f)); // debugSpeakMsg(attacker, "Eat hot dot increase: " + (strength - strold) + " strength: " + strength + " strold: " + strold); } // Duration is modified by dissipation skill mods. int dissipation_mod; if (type.equals(DOT_BLEEDING)) dissipation_mod = getEnhancedSkillStatisticModifier(target, "dissipation_bleeding"); else if (type.equals(DOT_POISON)) dissipation_mod = getEnhancedSkillStatisticModifier(target, "dissipation_poison"); else if (type.equals(DOT_DISEASE)) dissipation_mod = getEnhancedSkillStatisticModifier(target, "dissipation_disease"); else if (type.equals(DOT_FIRE)) dissipation_mod = getEnhancedSkillStatisticModifier(target, "dissipation_fire"); else if (type.equals(DOT_ACID)) dissipation_mod = getEnhancedSkillStatisticModifier(target, "dissipation_acid"); else if (type.equals(DOT_ENERGY)) dissipation_mod = getEnhancedSkillStatisticModifier(target, "dissipation_energy"); else return false; if (dissipation_mod >0) { if (dissipation_mod > 90) dissipation_mod = 90; duration = (int)(duration * (1.0f - (dissipation_mod / 100.0f))); if (duration < 1) duration = 1; } //////////////////////////////////////////////////////////////////////// // Cap the amount of total DOT damage on a target to equal or below 1000 capDots(attacker, target, strength); // End Cap //////////////////////////////////////////////////////////////////////// // Set the objvars utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_TYPE, type); utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_ATTRIBUTE, attribute); utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_STRENGTH, strength); utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_DURATION, duration); utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_TIME_START, getGameTime()); if (handler != null) utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_HANDLER, handler); // NOTE: Attacker not guaranteed to be valid or loaded. Currently only used to track damage for permissions and xp. if (isIdValid(attacker)) utils.setScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_ATTACKER, attacker); // Send out the messageTo and system message int pulse; string_id old_effect_string; string_id new_effect_string; if (type.equals(DOT_BLEEDING)) { new_effect_string = SID_BLEEDING; old_effect_string = SID_BLEEDING_INCREASE; pulse = BLEEDING_PULSE; if (!buff.hasBuff(target, "bleeding")) { buff.applyBuff(target, attacker, "bleeding"); setState(target, STATE_BLEEDING, true); playClientEffectObj(target, "appearance/pt_state_bleeding.prt", target, "spine3", null, "state_bleeding"); playClientEffectObj(target, "sound/sta_bleeding_on.snd", target, ""); } } else if (type.equals(DOT_POISON)) { old_effect_string = SID_POISONED_INCREASE; new_effect_string = SID_POISONED; pulse = POISON_PULSE; if (!buff.hasBuff(target, "poisoned")) { buff.applyBuff(target, attacker, "poisoned"); setState(target, STATE_POISONED, true); playClientEffectObj(target, "appearance/pt_state_poisoned.prt", target, "", null, "state_poisoned"); playClientEffectObj(target, "sound/sta_poisoned_on.snd", target, ""); } } else if (type.equals(DOT_DISEASE)) { old_effect_string = SID_DISEASED_INCREASE; new_effect_string = SID_DISEASED; pulse = DISEASE_PULSE; if (!buff.hasBuff(target, "diseased")) { buff.applyBuff(target, attacker, "diseased"); setState(target, STATE_DISEASED, true); playClientEffectObj(target, "appearance/pt_state_diseased.prt", target, "", null, "state_diseased"); playClientEffectObj(target, "sound/sta_diseased_on.snd", target, ""); } } else if (type.equals(DOT_FIRE)) { // Cannot get fire dots while swimming if (getState(target, STATE_SWIMMING) != 1) { pulse = FIRE_PULSE; old_effect_string = SID_FIRE_INCREASE; new_effect_string = SID_FIRE; if (!buff.hasBuff(target, "onfire")) { new_dot_type = true; buff.applyBuff(target, attacker, "onfire"); setState(target, STATE_ON_FIRE, true); playClientEffectObj(target, "appearance/pt_state_onfire.prt", target, "", null, "state_onfire"); playClientEffectObj(target, "sound/sta_onfire_on.snd", target, ""); } } else return false; } else if (type.equals(DOT_ACID)) { old_effect_string = SID_ACID_INCREASE; new_effect_string = SID_ACID; pulse = ACID_PULSE; if (!buff.hasBuff(target, "acid")) { buff.applyBuff(target, attacker, "acid"); // setState(target, STATE_DISEASED, true); playClientEffectObj(target, "appearance/pt_state_acid.prt", target, "", null, "state_acid"); playClientEffectObj(target, "sound/wep_heavy_acid_launcher_hit.snd", target, ""); } } else if (type.equals(DOT_ENERGY)) { old_effect_string = SID_ENERGY_INCREASE; new_effect_string = SID_ENERGY; pulse = ENERGY_PULSE; if (!buff.hasBuff(target, "energy")) { buff.applyBuff(target, attacker, "energy"); // setState(target, STATE_DISEASED, true); playClientEffectObj(target, "appearance/pt_state_energy.prt", target, "", null, "state_energy"); playClientEffectObj(target, "sound/item_electronics_break.snd", target, ""); } } else return false; // Getting hit with a new dot removes dot grace if (utils.hasScriptVar(target, SCRIPT_VAR_DOT_GRACE)) utils.removeScriptVar(target, SCRIPT_VAR_DOT_GRACE); // Attach the dot script if (!hasScript(target, SCRIPT_PLAYER_DOT)) attachScript(target, SCRIPT_PLAYER_DOT); if(type.equals(DOT_DISEASE)) { _applyDiseaseDamage(target, dot_id); } // If the dot is stacking with an existing dot_id, no need to send another message. if (!stacking) { dictionary d = new dictionary(); d.put("dot_id", dot_id); d.put("pulse", pulse); d.put("attacker", attacker); messageTo(target, "OnDotPulse", d, pulse, false); } applyDotDamage(target, dot_id); if (verbose) { if (new_dot_type) combat.sendCombatSpamMessage(target, new_effect_string); else combat.sendCombatSpamMessage(target, old_effect_string); } return true; } boolean canApplyDotType(obj_id target, string type) { int niche = ai_lib.aiGetNiche(target); if (!isIdValid(target)) return false; if (vehicle.isVehicle(target)) return false; prose_package pp = new prose_package(); if (niche == NICHE_DROID || niche == NICHE_ANDROID) { if (type.equals(DOT_POISON) || type.equals(DOT_DISEASE)) { pp = prose.setStringId(pp, new string_id("spam", "unaffected")); showFlyTextPrivateProseWithFlags(target, target, pp, 1.5f, colors.MEDIUMPURPLE, FLY_TEXT_FLAG_IS_DOT ); return false; } } if (niche == NICHE_VEHICLE) { if (type.equals(DOT_POISON) || type.equals(DOT_DISEASE)) { pp = prose.setStringId(pp, new string_id("spam", "unaffected")); showFlyTextPrivateProseWithFlags(target, target, pp, 1.5f, colors.MEDIUMPURPLE, FLY_TEXT_FLAG_IS_DOT ); return false; } } if (ai_lib.isTurret(target)) { if (type.equals(DOT_POISON) || type.equals(DOT_DISEASE)) { pp = prose.setStringId(pp, new string_id("spam", "unaffected")); showFlyTextPrivateProseWithFlags(target, target, pp, 1.5f, colors.MEDIUMPURPLE, FLY_TEXT_FLAG_IS_DOT ); return false; } } // Acid and Electrical DOT's affect all types. if (checkForDotImmunity(target, type)) { return false; } return true; }//end canApplyDotType /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyDotEffect(obj_id target, string type, string dot_id, int strength, int duration) { return applyDotEffect(target, null, type, dot_id, HEALTH, 100, strength, duration, true, null); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyDotEffect(obj_id target, string type, string dot_id, int attribute, int potency, int strength, int duration, boolean verbose) { return applyDotEffect(target, null, type, dot_id, attribute, potency, strength, duration, verbose, null); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyDotEffect(obj_id target, string type, string dot_id, int attribute, int potency, int strength, int duration) { return applyDotEffect(target, null, type, dot_id, attribute, potency, strength, duration, true, null); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyBleedingEffect(obj_id target, string dot_id, int attribute, int strength, int duration) { if(!isPlayer(target)) { if((ai_lib.aiGetNiche(target)==NICHE_DROID)|| ai_lib.isAndroid(target)||(ai_lib.aiGetNiche(target)==NICHE_VEHICLE)||(vehicle.isDriveableVehicle(target))) { return false; // droid! or a vehicle } } return applyDotEffect(target, null, DOT_BLEEDING, dot_id, attribute, 150, strength, duration, true, "bleedingStopped"); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyFireEffect(obj_id target, string dot_id, int strength, int duration) { return applyDotEffect(target, null, DOT_FIRE, dot_id, HEALTH, 150, strength, duration, true, "bleedingStopped"); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyDotEffect(obj_id target, obj_id attacker, string type, string dot_id, int attribute, int potency, int strength, int duration) { return applyDotEffect(target, attacker, type, dot_id, attribute, potency, strength, duration, true, null); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyBleedingEffect(obj_id target, obj_id attacker, string dot_id, int attribute, int strength, int duration) { if(!isPlayer(target)) { if((ai_lib.aiGetNiche(target)==NICHE_DROID) || ai_lib.isAndroid(target)||(ai_lib.aiGetNiche(target)==NICHE_VEHICLE)||(vehicle.isDriveableVehicle(target))) { return false; // droid! or a vehicle } } return applyDotEffect(target, attacker, DOT_BLEEDING, dot_id, attribute, 150, strength, duration, true, "bleedingStopped"); } /*********************************************************************** * @brief Overload for applyDotEffect * * @return boolean ***********************************************************************/ boolean applyFireEffect(obj_id target, obj_id attacker, string dot_id, int strength, int duration) { return applyDotEffect(target, attacker, DOT_FIRE, dot_id, HEALTH, 150, strength, duration, true, "bleedingStopped"); } /*********************************************************************** * @brief removes a dot of the specified dot_id from the given target * * @param obj_id target * @param string dot_id * @param boolean verbose * * @return boolean true on resist false on error or not resisted ***********************************************************************/ boolean removeDotEffect(obj_id target, string dot_id, boolean verbose) { ////LOG("LOG_CHANNEL", "dot::removeDotEffect -- " + dot_id); if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::removeDotEffect -- target is null"); return false; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::removeDotEffect -- dot_id is null"); return false; } if (!hasDotId(target, dot_id)) return false; else { string type = getDotType(target, dot_id); // Get the message handle for dot removal. string handler = getDotHandler(target, dot_id); // Remove the dot objvar. ////LOG("LOG_CHANNEL", "dotname ->" + getDotObjVarName(dot_id)); utils.removeScriptVarTree(target, getDotScriptVarName(dot_id)); // Check to see if this is the last dot on the player. string[] dots = getAllDots(target); if (dots == null) { utils.removeScriptVarTree(target, VAR_DOT_ROOT); int[] dotBuffs = buff.getAllBuffsByEffect(target, "dot"); if(dotBuffs == null && hasScript(target, SCRIPT_PLAYER_DOT)) detachScript(target, SCRIPT_PLAYER_DOT); } // Send a message to the target if we have a handler. if (handler != null) { dictionary d = new dictionary(); messageTo(target, handler, d, 0, true); } // Check to see if there are any dots of the given type left. If not, send a message. string[] dots_type = getAllDotsType(target, type); if (dots_type == null) { if (type.equals(DOT_BLEEDING)) { if (verbose) combat.sendCombatSpamMessage(target, SID_BLEEDING_STOP); setState(target, STATE_BLEEDING, false); stopClientEffectObjByLabel(target, "state_bleeding"); playClientEffectObj(target, "sound/sta_bleeding_off.snd", target, ""); if (!isBleeding(target)) buff.removeBuff(target, "bleeding"); } else if (type.equals(DOT_POISON)) { if (verbose) combat.sendCombatSpamMessage(target, SID_POISONED_STOP); setState(target, STATE_POISONED, false); stopClientEffectObjByLabel(target, "state_poisoned"); playClientEffectObj(target, "sound/sta_poisoned_off.snd", target, ""); if (!isPoisoned(target)) buff.removeBuff(target, "poisoned"); } else if (type.equals(DOT_DISEASE)) { if (verbose) combat.sendCombatSpamMessage(target, SID_DISEASED_STOP); setState(target, STATE_DISEASED, false); stopClientEffectObjByLabel(target, "state_diseased"); playClientEffectObj(target, "sound/sta_diseased_off.snd", target, ""); if(hasAttribModifier(target, "dot.disease." + dot_id)) removeAttribOrSkillModModifier(target, "dot.disease." + dot_id); if (!isDiseased(target)) buff.removeBuff(target, "diseased"); } else if (type.equals(DOT_FIRE)) { if (verbose) combat.sendCombatSpamMessage(target, SID_FIRE_STOP); setState(target, STATE_ON_FIRE, false); stopClientEffectObjByLabel(target, "state_onfire"); playClientEffectObj(target, "sound/sta_onfire_off.snd", target, ""); if (!isOnFire(target)) buff.removeBuff(target, "onfire"); } else if (type.equals(DOT_ACID)) { if (verbose) combat.sendCombatSpamMessage(target, SID_ACID_STOP); // setState(target, STATE_ON_FIRE, false); stopClientEffectObjByLabel(target, "state_acid"); // playClientEffectObj(target, "sound/sta_onfire_off.snd", target, ""); if (!isAcid(target)) buff.removeBuff(target, "acid"); } else if (type.equals(DOT_ENERGY)) { if (verbose) combat.sendCombatSpamMessage(target, SID_ENERGY_STOP); // setState(target, STATE_ON_FIRE, false); stopClientEffectObjByLabel(target, "state_energy"); // playClientEffectObj(target, "sound/sta_onfire_off.snd", target, ""); if (!isEnergy(target)) buff.removeBuff(target, "energy"); } } else { if (verbose) { if (type.equals(DOT_BLEEDING)) combat.sendCombatSpamMessage(target, SID_BLEEDING_DECREASE); else if (type.equals(DOT_POISON)) combat.sendCombatSpamMessage(target, SID_POISONED_DECREASE); else if (type.equals(DOT_DISEASE)) combat.sendCombatSpamMessage(target, SID_DISEASED_DECREASE); else if (type.equals(DOT_FIRE)) combat.sendCombatSpamMessage(target, SID_FIRE_DECREASE); else if (type.equals(DOT_ACID)) combat.sendCombatSpamMessage(target, SID_ACID_DECREASE); else if (type.equals(DOT_ENERGY)) combat.sendCombatSpamMessage(target, SID_ENERGY_DECREASE); } } return true; } } /*********************************************************************** * @brief Overload for removeDotEffect * * @param obj_id target * @param string dot_id * * @return boolean true on resist false on error or not resisted ***********************************************************************/ boolean removeDotEffect(obj_id target, string dot_id) { return removeDotEffect(target, dot_id, true); } /*********************************************************************** * @brief Removes all dots from the specified target. * * @param obj_id target * @param string dot_id * * @return boolean true on resist false on error or not resisted ***********************************************************************/ boolean removeAllDots(obj_id target) { ////LOG("LOG_CHANNEL", "dot::removeAllDots"); if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::removeAllDots -- target is null"); return false; } string[] dots = getAllDots(target); if (dots != null) { for (int i = 0; i < dots.length; i++) removeDotEffect(target, dots[i], false); } return true; } /*********************************************************************** * @brief Removes all dots from the specified target, of a specified type. * * @param obj_id target * @param string dot_id * * @return boolean true on resist false on error or not resisted ***********************************************************************/ boolean removeDotsOfType(obj_id target, string type) { if (!isIdValid(target)) { return false; } string[] dots = getAllDotsType(target, type); if (dots != null) { for (int i = 0; i < dots.length; i++) { removeDotEffect(target, dots[i], false); } return true; } return false; } boolean _applyDiseaseDamage(obj_id target, string dot_id) { int strength = utils.getIntScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_STRENGTH); int absorption_mod = getEnhancedSkillStatisticModifier(target, "absorption_disease"); if (absorption_mod > 0) { if (absorption_mod > 90) absorption_mod = 90; strength = (int)(strength * (1.0f - (absorption_mod / 100.0f))); } float duration = (float)utils.getIntScriptVar(target, VAR_DOT_ROOT + dot_id + VAR_DURATION); float up = duration * 0.75f; float down = duration * 0.25f; if(addAttribModifier(target, "dot.disease." + dot_id, ACTION, (-1 * strength), duration, up, down, false, true, false)) { displayDiseaseEffect(getLocation(target)); obj_id attacker = dot.getDotAttacker(target, dot_id); if (isIdValid(attacker) && exists(attacker)) { xp.updateCombatXpList(target, attacker, xp.PERMISSIONS_ONLY, strength); if(!isPlayer(target)) { addHate(target, attacker, strength); addHate(attacker, target, 0.0f); } } else { xp.updateCombatXpList(target, target, xp.PERMISSIONS_ONLY, strength); } } else return false; return true; } /*********************************************************************** * @brief applies the damage of the specifed dot * * @param obj_id target * @param string dot_id * * @return boolean false on error or duration over ***********************************************************************/ boolean applyDotDamage(obj_id target, string dot_id) { if (!isIdValid(target)) return false; if (dot_id == null) return false; if (!hasDotId(target, dot_id)) return false; string type = dot.getDotType(target, dot_id); if (type == null) return false; int strength = dot.getDotStrength(target, dot_id); int duration = dot.getDotDuration(target, dot_id); string dotScriptVar = getDotScriptVarName(dot_id); // No damage is dealt when the player is under grace period, incapped, or dead if (!utils.hasScriptVar(target, SCRIPT_VAR_DOT_GRACE)) { if (isDead(target) || isIncapacitated(target)) return true; } else return true; // Absorption skill mods on the target reduce the effective strength of the dot during damage pulses. int absorption_mod = 0; int vulnerability_mod = (int)getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_all"); dictionary protDic = armor.getCombatArmorSpecialProtections(target); float resistance = 0.0f; if(isPlayer(target)) { resistance = (float)armor.getCombatArmorGeneralProtection(target); } if(type.equals(DOT_BLEEDING)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_bleeding"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_bleed"); if(isPlayer(target)) { resistance += protDic.getFloat("cold"); } else { // resistance += combat.getNpcArmorProtection(target, DAMAGE_ELEMENTAL_COLD); resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_POISON)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_poison"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_poison"); if(isPlayer(target)) { resistance += protDic.getFloat("acid"); } else { // resistance += combat.getNpcArmorProtection(target, DAMAGE_ELEMENTAL_ACID); resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_DISEASE)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_disease"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_disease"); if(isPlayer(target)) { resistance += protDic.getFloat("cold"); } else { // resistance += combat.getNpcArmorProtection(target, DAMAGE_ELEMENTAL_COLD); resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_FIRE)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_fire"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_fire"); if(isPlayer(target)) { resistance += protDic.getFloat("heat"); } else { // resistance += combat.getNpcArmorProtection(target, DAMAGE_ELEMENTAL_HEAT); resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_ACID)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_acid"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_acid"); if(isPlayer(target)) { resistance += protDic.getFloat("acid"); } else { // resistance += combat.getNpcArmorProtection(target, DAMAGE_ELEMENTAL_ACID); resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_ENERGY)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_energy"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_energy"); if(isPlayer(target)) { resistance += protDic.getFloat("energy"); } else { // resistance += combat.getNpcArmorProtection(target, DAMAGE_ELEMENTAL_ELECTRICAL); resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else return false; // absorption reduces the strength of a dot by the given %. int damageAbsorbed = 0; if (absorption_mod > 0) { if (absorption_mod > 50) absorption_mod = 50; damageAbsorbed = (int)(strength * (absorption_mod / 100.0f)); strength = (int)(strength * (1.0f - (absorption_mod / 100.0f))); } if (vulnerability_mod > 0) { strength = (int)(strength * (1.0f + (vulnerability_mod / 100.0f))); } // Bring over the generic damage multiply/divisor from combat base to apply to dot damage. // Generic DoT's have no caster int expertiseDamageBonus = getEnhancedSkillStatisticModifierUncapped(target, "combat_multiply_damage_taken"); float tempDamageFloat = (float)strength; tempDamageFloat = tempDamageFloat * (1.0f + ((float)expertiseDamageBonus / 100.0f) ); int expertiseDamageReduction = getEnhancedSkillStatisticModifierUncapped(target, "combat_divide_damage_taken"); expertiseDamageReduction = expertiseDamageReduction > 100 ? 100 : expertiseDamageReduction; tempDamageFloat = tempDamageFloat * (1.0f - ((float)expertiseDamageReduction / 100.0f)); strength = (int)tempDamageFloat; // Dots don't incap. Reduce strength to one less than the current attribute if necessary. int current_attrib = getAttrib(target, HEALTH); //Disease dots are a primary action debuff and they also damage action at a rate of 33% of the potency. if (type.equals(DOT_DISEASE)) { current_attrib = getAttrib(target, ACTION); strength = Math.round((float)strength / 3.0f); } /* if (current_attrib <= strength) strength = current_attrib - 1; */ obj_id attacker = dot.getDotAttacker(target, dot_id); // If a player was hit by a dot at one point and was attackable, but now is not, the dot should be removed. if( (attacker != target) && !pvpCanAttack(attacker, target)) { removeDotEffect(target, dot_id); return false; } // Per tick resist area, this gives you a chance to nulify that ticks damage int damageResisted = 0; if(attemptDotResist(target, type, 100, false)) { int divisor = rand(2, 25); int oldStrength = strength; strength /= divisor; damageResisted = oldStrength - strength; } string mitigationString = "("+damageAbsorbed + getString(new string_id("dot_message", "generic_absorbed"))+damageResisted+getString(new string_id("dot_message", "generic_resisted"))+")"; if(strength > 0) { hit_result hit = new hit_result(); hit.damage = strength; hit.success = true; string_id strSpam = new string_id("combat_effects", "damage_fly"); prose_package ppFly = new prose_package(); ppFly = prose.setStringId(ppFly, strSpam); ppFly = prose.setDI(ppFly, -strength); prose_package ppSpam = new prose_package(); if(type.equals(dot.DOT_BLEEDING)) { // Track damage for xp calcs if (isIdValid(attacker) && !isDead(attacker)) { ppSpam = prose.setStringId(ppSpam, SID_BLEED_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, attacker); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(attacker, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,attacker,ppFly, 1f, colors.INDIANRED, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_BLEED_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,target,ppFly, 1f, colors.INDIANRED, FLY_TEXT_FLAG_IS_DOT); } } else if(type.equals(dot.DOT_POISON)) { if (isIdValid(attacker) && !isDead(attacker)) { ppSpam = prose.setStringId(ppSpam, SID_POISON_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, attacker); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(attacker, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,attacker,ppFly, 1f, colors.YELLOWGREEN, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_POISON_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,target,ppFly, 1f, colors.YELLOWGREEN, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(dot.DOT_DISEASE)) { if (isIdValid(attacker) && !isDead(attacker)) { ppSpam = prose.setStringId(ppSpam, SID_DISEASE_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, attacker); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(attacker, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,attacker,ppFly, 1f, colors.LIMEGREEN, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_DISEASE_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,target,ppFly, 1f, colors.LIMEGREEN, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(dot.DOT_FIRE)) { if (isIdValid(attacker) && !isDead(attacker)) { ppSpam = prose.setStringId(ppSpam, SID_FIRE_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, attacker); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(attacker, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, attacker, ppFly, 1f, colors.FIREBRICK, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_FIRE_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.FIREBRICK, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(dot.DOT_ACID)) { if (isIdValid(attacker) && !isDead(attacker)) { ppSpam = prose.setStringId(ppSpam, SID_ACID_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, attacker); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(attacker, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, attacker, ppFly, 1f, colors.OLIVEDRAB, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_ACID_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.OLIVEDRAB, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(dot.DOT_ENERGY)) { if (isIdValid(attacker) && !isDead(attacker)) { ppSpam = prose.setStringId(ppSpam, SID_ENERGY_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, attacker); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(attacker, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, attacker, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_ENERGY_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } } else { return false; } if (!type.equals(DOT_DISEASE)) { doDamage(attacker, target, hit); } else drainAttributes(target, strength, 0); if(isIdValid(attacker) && isIdValid(target) && exists(attacker) && exists(target)) { startCombat(attacker, target); startCombat(target, attacker); } // Track damage for xp calcs if(isIdValid(attacker) && !isDead(attacker)) { //try to assign xp based on weapon used obj_id myWeapon = getCurrentWeapon(attacker); if(isIdValid(myWeapon)) xp.updateCombatXpList(target, attacker, myWeapon, strength); else //since the type no longer matters, we will give rifle. If we gave general we wouldnt be giving full credit. xp.updateCombatXpList(target, attacker, xp.COMBAT_RANGEDSPECIALIZE_RIFLE, strength); } else { xp.updateCombatXpList(target, target, xp.PERMISSIONS_ONLY, strength); } if(!isPlayer(target)) { if(isIdValid(attacker) && exists(attacker)) { addHate(target, attacker, strength); addHate(attacker, target, 0.0f); } } } int pulse = getDotPulse(target, dot_id); // Reduce the duration. Remove the duration if it's over. duration = duration - pulse; if (duration < 1) { removeDotEffect(target, dot_id); return false; } else { // Need to check again in case the damage, itself, triggered a removal in another system. if (hasDotId(target, dot_id)) utils.setScriptVar(target, dotScriptVar + VAR_DURATION, duration); return true; } } /*********************************************************************** * @brief applies bleeding, and other special dot effects caused by * weapons. * * @param obj_id attacker * @param obj_id defender * @param hit_result results as passed by the combat system * @param weapon_data weapon as passed by the combat system * @param float bleeding_mult multiplier to the bleeding severity * * @return boolean false on error or no dot applied ***********************************************************************/ boolean applyCombatDots(obj_id attacker, obj_id defender, hit_result results, weapon_data weapon, float bleeding_mult) { ////LOG("LOG_CHANNEL", "dot::applyCombatDots -- " + attacker + " " + defender); if (!isIdValid(attacker)) { ////LOG("LOG_CHANNEL", "dot::applyCombatBleeding -- attacker is null"); return false; } if (!isIdValid(defender)) { ////LOG("LOG_CHANNEL", "dot::applyCombatBleeding -- defender is null"); return false; } if (results == null) { ////LOG("LOG_CHANNEL", "dot::applyCombatBleeding -- results is null"); return false; } if (weapon == null) { //LOG("LOG_CHANNEL", "dot::applyCombatBleeding -- weapon is null"); return false; } // ***** calculate bleeding ***** int hit_location = results.hitLocation; float damage = (float)results.damage; float wound_rating = weapon.woundChance; if (damage < 1) return false; // Get attacker's bleeding mods. float attacker_mod = getEnhancedSkillStatisticModifier(attacker, "combat_bleeding_attack"); // Get defenders bleeding defense. float defender_mod = getEnhancedSkillStatisticModifier(attacker, "combat_bleeding_defense"); // The chance to cause bleeding is a function of damage, weapon wound rating, attacker and defender // skill mods. float bleeding_base = damage * (1.0f + (attacker_mod - defender_mod) / 100.0f) / 50.0f; // Reduced bleeding base by a factor of 50 [DW] float bleeding_chance = bleeding_base + wound_rating; ////LOG("LOG_CHANNEL", "bleeding_base ->" + bleeding_base + " bleeding_chance ->" + bleeding_chance); boolean dot_applied = false; // Check for bleeding if (rand(1,10000) <= bleeding_chance) // decreased chance of bleeding by a factor of 100 [DW] { // Apply bleeding effect. float strength = bleeding_base / 30; // Reduced bleeding strength by a factor of 10 [DW] float duration = rand(120, 300) * (1.0f + (attacker_mod - defender_mod) / 100.0f); string hit_location_str = "combat_bleeding"; //HIT_LOCATIONS[hit_location]; // Removed bleeding per hit location int attribute = HIT_LOCATION_ATTRIBUTE[hit_location]; //LOG("LOG_CHANNEL", "strength ->" + strength + " duration ->" + duration + " attribute ->" + attribute); if (strength > 0) applyBleedingEffect(defender, attacker, hit_location_str, attribute, (int)strength, (int)duration); dot_applied = true; } // ***** apply special weapon dot effects ***** obj_id weapon_id = weapon.id; if (combat.hasCertification(attacker, weapon_id)) { if (utils.hasScriptVarTree(weapon_id, VAR_DOT)) { string[] weapon_dots = getAllDots(weapon_id); if (weapon_dots != null) { for (int i = 0; i < weapon_dots.length; i++) { string type = getDotType(weapon_id, weapon_dots[i]); int attribute = getDotAttribute(weapon_id, weapon_dots[i]); int potency = getDotPotency(weapon_id, weapon_dots[i]); int strength = getDotStrength(weapon_id, weapon_dots[i]); int duration = getDotDuration(weapon_id, weapon_dots[i]); if (canApplyDotType(defender, type)) { applyDotEffect(defender, attacker, type, weapon_dots[i], attribute, potency, strength, duration, true, null); decrementDotUses(weapon_id, weapon_dots[i]); dot_applied = true; } } } } } return dot_applied; } /*********************************************************************** * @brief changes the strength of a specific dot effect * * @param obj_id target * @param string dot_id * @param int strength change in current strength * @param boolean verbose * * @return boolean true on success false on error or not resisted ***********************************************************************/ boolean modifyDotEffectStrength(obj_id target, string dot_id, int strength, boolean verbose) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::modifyDotEffectStrength -- target is null"); return false; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::modifyDotEffectStrength -- dot_id is null"); return false; } if (!hasDotId(target, dot_id)) return false; int current_strength = getDotStrength(target, dot_id); string type = getDotType(target, dot_id); if (current_strength == -1) { //LOG("LOG_CHANNEL", "dot::modifyDotEffectStrength -- error in trying to read strength for " + dot_id); return false; } current_strength = current_strength + strength; if (current_strength < 1) removeDotEffect(target, dot_id, verbose); else { utils.setScriptVar(target, getDotScriptVarName(dot_id) + VAR_STRENGTH, current_strength); if (verbose) { if (type.equals(DOT_BLEEDING)) combat.sendCombatSpamMessage(target, SID_BLEEDING_DECREASE); else if (type.equals(DOT_POISON)) combat.sendCombatSpamMessage(target, SID_POISONED_DECREASE); else if (type.equals(DOT_DISEASE)) combat.sendCombatSpamMessage(target, SID_DISEASED_DECREASE); else if (type.equals(DOT_FIRE)) combat.sendCombatSpamMessage(target, SID_FIRE_DECREASE); else if (type.equals(DOT_ACID)) combat.sendCombatSpamMessage(target, SID_FIRE_DECREASE); else if (type.equals(DOT_ENERGY)) combat.sendCombatSpamMessage(target, SID_FIRE_DECREASE); } } return true; } /*********************************************************************** * @brief gets all dots of the specifed type on a target and reduces total strength * by the specified amount. If there is more reduction than * strength in a given dot, the dot is removed and the next one * in the list is affected. * * @param obj_id target * @param string dot_id * @param int strength change in current strength * * @return int the total strength reduced. -1 on fail. ***********************************************************************/ int reduceDotTypeStrength(obj_id target, string type, int strength) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::reduceDotTypeStrength -- target is null"); return -1; } if(!isMob(target)) { return -1; } if (type == null) { //LOG("LOG_CHANNEL", "dot::reduceDotTypeStrength -- dot_id is null"); return -1; } if (strength < 1) { //LOG("LOG_CHANNEL", "dot::reduceDotTypeStrength -- strength value " + strength + " is illegal."); return -1; } string[] dots = getAllDotsType(target, type); if (dots == null) return -1; // Loop through all dots of the specified type reducing their strength until the total // is reached. int remaining_strength = strength; for (int i = 0; i < dots.length; i++) { int dot_strength = getDotStrength(target, dots[i]); if (dot_strength <= remaining_strength) { remaining_strength = remaining_strength - dot_strength; // If the dot's strength is reduced to zero, remove it. if (remaining_strength < 1 || i == dots.length - 1) removeDotEffect(target, dots[i], true); else removeDotEffect(target, dots[i], false); } else { dot_strength = dot_strength - remaining_strength; modifyDotEffectStrength(target, dots[i], -remaining_strength, true); remaining_strength = 0; break; } } return strength - remaining_strength; } /*********************************************************************** * @brief checks to see whether or not the given dot is resisted on application of the DoT * * @param obj_id target * @param string type * @param int potency * * @return boolean true on resist false on error or not resisted ***********************************************************************/ boolean attemptDotResist(obj_id target, string type, int potency, boolean showResistFlytext) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::attemptDotResist -- target is null"); return false; } if (type == null) { //LOG("LOG_CHANNEL", "dot::attemptDotResist -- type is null"); return false; } // Incapacitated and dead targets always resist dots. if (isIncapacitated(target) || isDead(target)) return true; if (potency < 0) { if (potency == -1) { // Potency of -1 can't be resisted. return false; } else { //LOG("LOG_CHANNEL", "dot::attemptDotResist -- potency value of " + potency + " is illegal."); return false; } } int resistance_mod = 0; if(type.equals(DOT_BLEEDING)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_bleeding"); } else if(type.equals(DOT_POISON)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_poison"); } else if(type.equals(DOT_DISEASE)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_disease"); } else if(type.equals(DOT_FIRE)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_fire"); } else if(type.equals(DOT_ACID)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_acid"); } else if(type.equals(DOT_ENERGY)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_energy"); } else if(type.equals(DOT_ELECTRICITY)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_eletricity"); } else if(type.equals(DOT_COLD)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_cold"); } else if(type.equals(DOT_KINETIC)) { resistance_mod = getEnhancedSkillStatisticModifier(target, "resistance_kinetic"); } else { //LOG("LOG_CHANNEL", "dot::attemptDotResist -- dot type " + type + " not found."); return false; } //sendSystemMessageTestingOnly(target, "resistance_mod = "+resistance_mod); // The resistance check formula is a scaled linear resistance based on a comparison of the // resisance value to the potency value. This formula causes the base resist rate to go up // as the resistance increases as well as decreasing the effectiveness of each point of potency. //with Reverse engineering players were resisting up to around 72% of the dots //we needed to nerf this down resistance_mod /= MOD_DIVISOR; float resist_scale = (0.4f / ((100f + resistance_mod) / 200f)); // Scale of the resistance curve based on resist value float to_hit_chance = potency * resist_scale; // hit chance based on potency vs resist_mod // Cap reistance values to 5% & 95% if (to_hit_chance < 5) to_hit_chance = 5; if (to_hit_chance > 95) to_hit_chance = 95; if ((int)rand(1, 100) < to_hit_chance) { ////LOG("LOG_CHANNEL", "dot not resisted."); return false; } else { if(showResistFlytext) { combat.sendCombatSpamMessage(target, SID_DOT_RESISTED_SPAM); prose_package pp = new prose_package(); pp = prose.setStringId(pp, new string_id("spam", "unaffected")); showFlyTextPrivateProseWithFlags(target, target, pp, 1.5f, colors.MEDIUMPURPLE, FLY_TEXT_FLAG_IS_DOT ); } return true; } } /*********************************************************************** * @brief checks to see whether or not the target has the specified * dot_id * * @param obj_id target * @param string dot_id * * @return boolean ***********************************************************************/ boolean hasDotId(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::hasDotId -- target is null"); return false; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::hasDotId -- dot_id is null"); return false; } string scriptvar_name = getDotScriptVarName(dot_id); if (utils.hasScriptVarTree(target, scriptvar_name)) return true; else return false; } /*********************************************************************** * @brief returns the scriptvar name given the dot_id * * @param string dot_id * * @return string ***********************************************************************/ string getDotScriptVarName(string dot_id) { return VAR_DOT_ROOT + dot_id; } /*********************************************************************** * @brief returns all dot_ids on a target * * @param obj_id target * @param string type * * @return string[] null on error or none exists ***********************************************************************/ string[] getAllDots(obj_id target) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getAllDots -- target is null"); return null; } // Define a HashSet to store the dot names (so that we don't have duplicates) HashSet dots_found = new HashSet(); // Go through all the script var keys and extract dot_id values deltadictionary dd = target.getScriptVars(); Enumeration keys = dd.keys(); while ( keys.hasMoreElements() ) { string key = (string)(keys.nextElement()); if ( key.startsWith(VAR_DOT_ROOT) ) { int dotIndex = key.indexOf("."); if (dotIndex > -1) { // Remove the VAR_DOT_ROOT from the beginning of the key String dotItem = key.substring(dotIndex + 1); // Find the next "." so that we can extract the dot_id dotIndex = dotItem.indexOf("."); if (dotIndex > -1) { // Strip off everything after the dot_id value String dotId = dotItem.substring(0, dotIndex); dots_found.add(dotId); } } } } if (dots_found.size() < 1) return null; else { // Return the list as a string[] String[] dot_string = new String[dots_found.size()]; dots_found.toArray(dot_string); return dot_string; } } /*********************************************************************** * @brief returns all dot_ids on a target of the specified type * * @param obj_id target * @param string type * * @return string[] null on error or none exists ***********************************************************************/ string[] getAllDotsType(obj_id target, string type) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getAllDotsType -- target is null"); return null; } if (type == null) { //LOG("LOG_CHANNEL", "dot::getAllDotsType -- type is null"); return null; } Vector dots_found = new Vector(); // Iterate through the dot objvar list looking for dots of the specified type string[] dots = getAllDots(target); if (dots != null) { for (int i = 0; i < dots.length; ++i) { String scriptVarName = VAR_DOT_ROOT + dots[i] + VAR_TYPE; String scriptVarValue = utils.getStringScriptVar(target, scriptVarName); if ((scriptVarValue != null) && scriptVarValue.equals(type) ) { dots_found.addElement(dots[i]); } } } if (dots_found.size() < 1) return null; else { String[] dot_string = new String[dots_found.size()]; dots_found.toArray(dot_string); return dot_string; } } string[] getAllDotsOwner(obj_id owner, obj_id target) { if(!isIdValid(target)) { return null; } if(!isIdValid(target)) { return null; } Vector dots_found = new Vector(); // Iterate through the dot objvar list looking for dots of the specified type string[] dots = getAllDots(target); if (dots != null) { for (int i = 0; i < dots.length; ++i) { obj_id who = getDotAttacker(target, dots[i]); if(isIdValid(who) && owner == who) { dots_found.addElement(dots[i]); } } } if (dots_found.size() < 1) return null; else { String[] dot_string = new String[dots_found.size()]; dots_found.toArray(dot_string); return dot_string; } } void removeAllDotsOwner(obj_id owner, obj_id target) { string[] dots = getAllDotsOwner(owner, target); if(dots == null || dots.length == 0) return; for(int i = 0; i < dots.length; i++) { removeDotEffect(target, dots[i], false); } } /*********************************************************************** * @brief determines whether or not a target is bleeding * * @param obj_id target * * @return boolean ***********************************************************************/ boolean isBleeding(obj_id target) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::isBleeding -- target is null"); return false; } string[] dots = getAllDotsType(target, DOT_BLEEDING); if (dots != null) return true; else return false; } /*********************************************************************** * @brief determines whether or not a target is poisoned * * @param obj_id target * * @return boolean ***********************************************************************/ boolean isPoisoned(obj_id target) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::isPoisoned -- target is null"); return false; } string[] dots = getAllDotsType(target, DOT_POISON); if (dots != null) return true; else return false; } /*********************************************************************** * @brief determines whether or not a target is diseased * * @param obj_id target * * @return boolean ***********************************************************************/ boolean isDiseased(obj_id target) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::isDiseased -- target is null"); return false; } string[] dots = getAllDotsType(target, DOT_DISEASE); if (dots != null) return true; else return false; } /*********************************************************************** * @brief determines whether or not a target is on fire * * @param obj_id target * * @return boolean ***********************************************************************/ boolean isOnFire(obj_id target) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::isOnFire -- target is null"); return false; } string[] dots = getAllDotsType(target, DOT_FIRE); if (dots != null) return true; else return false; } /*********************************************************************** * @brief determines whether or not a target is acidic * * @param obj_id target * * @return boolean ***********************************************************************/ boolean isAcid(obj_id target) { if (!isIdValid(target)) { return false; } string[] dots = getAllDotsType(target, DOT_ACID); if (dots != null) return true; else return false; } /*********************************************************************** * @brief determines whether or not a target is on electrified * * @param obj_id target * * @return boolean ***********************************************************************/ boolean isEnergy(obj_id target) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::isOnFire -- target is null"); return false; } string[] dots = getAllDotsType(target, DOT_ENERGY); if (dots != null) return true; else return false; } /*********************************************************************** * @brief returns the dot type on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return string null on error or no dot of that id ***********************************************************************/ string getDotType(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotType -- target is null."); return null; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotType -- dot_id is null."); return null; } if (hasDotId(target, dot_id)) { return utils.getStringScriptVar(target, getDotScriptVarName(dot_id) + VAR_TYPE); } else return null; } /*********************************************************************** * @brief returns the dot attribute on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return int -1 on error or no dot of that id ***********************************************************************/ int getDotAttribute(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotAttribute -- target is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotAttribute -- dot_id is null."); return -1; } if (hasDotId(target, dot_id)) { return utils.getIntScriptVar(target, getDotScriptVarName(dot_id) + VAR_ATTRIBUTE); } else return -1; } /*********************************************************************** * @brief returns the dot potency on a given source for a given * dot_id. Works only on dot sources, not the target. * * @param obj_id source * @param string dot_id * * @return int -1 on error or no dot of that id ***********************************************************************/ int getDotPotency(obj_id source, string dot_id) { if (!isIdValid(source)) { //LOG("LOG_CHANNEL", "dot::getDotPotency -- source is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotPotency -- dot_id is null."); return -1; } if (hasDotId(source, dot_id)) { return utils.getIntScriptVar(source, getDotScriptVarName(dot_id) + VAR_POTENCY); } else return -1; } /*********************************************************************** * @brief returns the dot strength on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return int -1 on error or no dot of that id ***********************************************************************/ int getDotStrength(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotStrength -- target is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotStrength -- dot_id is null."); return -1; } if (hasDotId(target, dot_id)) { return utils.getIntScriptVar(target, getDotScriptVarName(dot_id) + VAR_STRENGTH); } else return -1; } /*********************************************************************** * @brief returns the dot duration on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return int -1 on error or no dot of that id ***********************************************************************/ int getDotDuration(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotDuration -- target is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotDuration -- dot_id is null."); return -1; } if (hasDotId(target, dot_id)) { return utils.getIntScriptVar(target, getDotScriptVarName(dot_id) + VAR_DURATION); } else return -1; } /*********************************************************************** * @brief returns the dot starttime on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return int -1 on error or no dot of that id ***********************************************************************/ int getDotStartTime(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotStartTime -- target is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotStartTime -- dot_id is null."); return -1; } if (hasDotId(target, dot_id)) { return utils.getIntScriptVar(target, getDotScriptVarName(dot_id) + VAR_TIME_START); } else return -1; } /*********************************************************************** * @brief returns the dot last pulse on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return int -1 on error or no dot of that id ***********************************************************************/ int getDotLastPulse(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotLastPulse -- target is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotLastPulse -- dot_id is null."); return -1; } if (hasDotId(target, dot_id)) { return utils.getIntScriptVar(target, getDotScriptVarName(dot_id) + VAR_LAST_PULSE); } else return -1; } /*********************************************************************** * @brief returns the dot handler on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return string null on error or no dot of that id ***********************************************************************/ string getDotHandler(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotHandler -- target is null."); return null; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotHandler -- dot_id is null."); return null; } if (hasDotId(target, dot_id)) { return utils.getStringScriptVar(target, getDotScriptVarName(dot_id) + VAR_HANDLER); } else return null; } /*********************************************************************** * @brief returns the attacker on a given target for a given * dot_id * * @param obj_id target * @param string dot_id * * @return obj_id null on error or no dot of that id ***********************************************************************/ obj_id getDotAttacker(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotAttacker -- target is null."); return null; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotAttacker -- dot_id is null."); return null; } if (hasDotId(target, dot_id)) { String scriptVarName = getDotScriptVarName(dot_id) + VAR_ATTACKER; if (utils.hasScriptVar(target, scriptVarName)) return utils.getObjIdScriptVar(target, scriptVarName); else return null; } else return null; } /*********************************************************************** * @brief returns the pulse time for given dot * * @param obj_id target * @param string dot_id * * @return int -1 on error ***********************************************************************/ int getDotPulse(obj_id target, string dot_id) { if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::getDotPulse -- target is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotPulse -- dot_id is null."); return -1; } string type = getDotType(target, dot_id); if (type == null) { //LOG("LOG_CHANNEL", "dot::getDotPulse -- dot type is null for " + target); return -1; } if (type.equals(dot.DOT_BLEEDING)) return dot.BLEEDING_PULSE; else if (type.equals(dot.DOT_POISON)) return dot.POISON_PULSE; else if (type.equals(dot.DOT_DISEASE)) return dot.DISEASE_PULSE; else if (type.equals(dot.DOT_FIRE)) return dot.FIRE_PULSE; else if (type.equals(dot.DOT_ACID)) return dot.ACID_PULSE; else if (type.equals(dot.DOT_ENERGY)) return dot.ENERGY_PULSE; else { //LOG("LOG_CHANNEL", "dot::getDotPulse -- dot type " + type + " not found."); return -1; } } /*********************************************************************** * @brief returns the number of uses left on a dot source * * @param obj_id target * @param string dot_id * * @return int -1 on error ***********************************************************************/ int getDotUses(obj_id source, string dot_id) { if (!isIdValid(source)) { //LOG("LOG_CHANNEL", "dot::getDotUses -- source is null."); return -1; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::getDotUses -- dot_id is null."); return -1; } if (hasDotId(source, dot_id)) { return utils.getIntScriptVar(source, getDotScriptVarName(dot_id) + VAR_USES); } else return -1; } /*********************************************************************** * @brief adds dot attack to am item * * @param obj_id item * @param string type * @param string dot_id * @param int attribute * @param int potency * @param int strength * @param int duration * * @return boolean ***********************************************************************/ boolean addDotAttackToItem(obj_id item, string type, string dot_id, int attribute, int potency, int strength, int duration, boolean stackable, int uses) { if (!isIdValid(item)) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- item is null"); return false; } if (type == null) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- type is null"); return false; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- dot_id is null"); return false; } if (attribute < 0 || attribute > 8) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- attribute value of " + attribute + " is illegal."); return false; } if (potency != -1 && potency < 1) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- potency value of " + potency + " is illegal."); return false; } if (strength < 1) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- strength value of " + strength + " is illegal."); return false; } if (duration < 1) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- duration value of " + duration + " is illegal."); return false; } if (uses != -1 && uses < 1) { //LOG("LOG_CHANNEL", "dot::addDotAttackToWeapon -- uses value of " + uses + " is illegal."); return false; } utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_TYPE, type); utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_ATTRIBUTE, attribute); utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_POTENCY, potency); utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_STRENGTH, strength); utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_DURATION, duration); utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_USES, uses); return true; } /*********************************************************************** * @brief reduces the number of dot uses on an item. * * @param obj_id item * @param string dot_id * * @return boolean fail on error ***********************************************************************/ boolean decrementDotUses(obj_id item, string dot_id) { if (!isIdValid(item)) { //LOG("LOG_CHANNEL", "dot::decrementDotUses -- item is null"); return false; } if (dot_id == null) { //LOG("LOG_CHANNEL", "dot::decrementDotUses -- dot_id is null"); return false; } if (!hasDotId(item, dot_id)) return false; int uses = getDotUses(item, dot_id); // Items with -1 uses don't run out. if (uses != - 1) { uses = uses - 1; if (uses < 1) utils.removeScriptVarTree(item, getDotScriptVarName(dot_id)); else utils.setScriptVar(item, VAR_DOT_ROOT + dot_id + VAR_USES, uses); } return true; } /*********************************************************************** * @brief displays the bleeding particle effect. * * @param location loc * * @return void ***********************************************************************/ void displayBleedingEffect(location loc) { if (loc == null) { //LOG("LOG_CHANNEL", "dot::displayBleedingEffect -- location is null"); return; } obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS); if (players != null) { for (int i = 0; i < players.length; i++) { playClientEffectLoc(players[i], "clienteffect/dot_bleeding.cef" , loc, 0); } } return; } /*********************************************************************** * @brief displays the poison particle effect. * * @param location loc * * @return void ***********************************************************************/ void displayPoisonEffect(location loc) { if (loc == null) { //LOG("LOG_CHANNEL", "dot::displayPoisonEffect -- location is null"); return; } obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS); if (players != null) { for (int i = 0; i < players.length; i++) { playClientEffectLoc(players[i], "clienteffect/dot_poisoned.cef" , loc, 0); } } return; } /*********************************************************************** * @brief displays the disease particle effect. * * @param location loc * * @return void ***********************************************************************/ void displayDiseaseEffect(location loc) { if (loc == null) { //LOG("LOG_CHANNEL", "dot::displayDiseaseEffect -- location is null"); return; } obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS); if (players != null) { for (int i = 0; i < players.length; i++) { playClientEffectLoc(players[i], "clienteffect/dot_diseased.cef" , loc, 0); } } return; } /*********************************************************************** * @brief displays the fire particle effect. * * @param location loc * * @return void ***********************************************************************/ void displayFireEffect(location loc) { if (loc == null) { //LOG("LOG_CHANNEL", "dot::displayDiseaseEffect -- location is null"); return; } obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS); if (players != null) { for (int i = 0; i < players.length; i++) { playClientEffectLoc(players[i], "clienteffect/dot_fire.cef" , loc, 0); } } return; } /*********************************************************************** * @brief displays the fire particle effect. * * @param location loc * * @return void ***********************************************************************/ void displayAcidEffect(location loc) { if (loc == null) { //LOG("LOG_CHANNEL", "dot::displayDiseaseEffect -- location is null"); return; } obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS); if (players != null) { for (int i = 0; i < players.length; i++) { playClientEffectLoc(players[i], "clienteffect/dot_fire.cef" , loc, 0); } } return; } /*********************************************************************** * @brief displays the fire particle effect. * * @param location loc * * @return void ***********************************************************************/ void displayEnergyEffect(location loc) { if (loc == null) { //LOG("LOG_CHANNEL", "dot::displayDiseaseEffect -- location is null"); return; } obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS); if (players != null) { for (int i = 0; i < players.length; i++) { playClientEffectLoc(players[i], "clienteffect/dot_fire.cef" , loc, 0); } } return; } /******************************************************************* *@brief checks to see if an immunity local var exists of the * same type as the dot attempting to be applied * *@param obj_id target, string type * *@return boolen (true if immunity exists, false if it does not) ********************************************************************/ boolean checkForDotImmunity(obj_id target, string type) { int resistVar = getEnhancedSkillStatisticModifierUncapped(target, "dot_resist_"+type); int universal = getEnhancedSkillStatisticModifierUncapped(target, "dot_resist_all"); int elemental = getElementalGroupResist(target, type); int natural = getNaturalGroupResist(target, type); int applyCheck = rand(0, 99); boolean wasResisted = false; if (applyCheck < resistVar) wasResisted = true; if (applyCheck < universal) wasResisted = true; if (applyCheck < elemental) wasResisted = true; if (applyCheck < natural) wasResisted = true; //debugSpeakMsg(target, "type: "+type+" and resist list was "+applyCheck+" vs - "+resistVar+", "+universal+", "+elemental+", "+natural); return wasResisted; } int getElementalGroupResist(obj_id target, string type) { if (!type.equals(DOT_FIRE) && !type.equals(DOT_ACID) && !type.equals(DOT_COLD) && !type.equals(DOT_ELECTRICITY) && !type.equals(DOT_ENERGY) && !type.equals(DOT_KINETIC)) { return 0; } return getEnhancedSkillStatisticModifierUncapped(target, "dot_resist_elemental"); } int getNaturalGroupResist(obj_id target, string type) { if (!type.equals(DOT_POISON) && !type.equals(DOT_DISEASE) && !type.equals(DOT_BLEEDING)) { return 0; } return getEnhancedSkillStatisticModifierUncapped(target, "dot_resist_natural"); } void capDots(obj_id attacker, obj_id target, int strength) { // If the target is not a player, don't cap the DOTs. if(!isIdValid(target) || !isIdValid(attacker) || !isPlayer(target) || !isPlayer(attacker)) { return; } // Don't cap dots if the attacker is not a player. if (!isPlayer(attacker) && (isIdValid(getMaster(attacker)) && !isPlayer(getMaster(attacker)))) { return; } string[] allDots = getAllDotsOwner(attacker, target); if(allDots == null) { return; } // If the amount of DOTs on the target is greater than what should be possible, remove the oldest. if(allDots.length >= DOT_MAXIMUM_COUNT) { int oldestDot = 0; for(int i = 1; i < allDots.length; i++) { if(getDotStartTime(target, allDots[oldestDot]) > getDotStartTime(target, allDots[i])) { oldestDot = i; } } removeDotEffect(target, allDots[oldestDot], true); } } int getDotResistanceMod(string type, obj_id target) { int dotResistanceMod = 0; if(isPlayer(target)) { if(utils.hasScriptVar(target, "armor.armor_type_tally")) { int[] armorTypeTally = utils.getIntArrayScriptVar(target, "armor.armor_type_tally"); if(armorTypeTally.length != 3) { return dotResistanceMod; } if (type.equals(DOT_BLEEDING)) // Recon 0 { dotResistanceMod = armorTypeTally[0] * armorTypeTally[0] * 2; } else if (type.equals(DOT_POISON)) // Battle 1 { dotResistanceMod = armorTypeTally[1] * armorTypeTally[1] * 2; } else if (type.equals(DOT_DISEASE)) // Recon 0 { dotResistanceMod = armorTypeTally[0] * armorTypeTally[0] * 2; } else if (type.equals(DOT_FIRE)) // Assault 2 { dotResistanceMod = armorTypeTally[2] * armorTypeTally[2] * 2; } else if (type.equals(DOT_ACID)) // Acid Assault 2 { dotResistanceMod = armorTypeTally[2] * armorTypeTally[2] * 2; } else if (type.equals(DOT_ENERGY)) // Energy Battle 1 { dotResistanceMod = armorTypeTally[1] * armorTypeTally[1] * 2; } } } else if(beast_lib.isBeast(target)) { float resilience = beast_lib.getBeastCustomMod(target, beast_lib.MOD_RESILIENCE); float survival = beast_lib.getBeastCustomMod(target, beast_lib.MOD_SURVIVAL); int beastResistMod = Math.round((resilience * resilience) + (survival * survival)); dotResistanceMod = beastResistMod; } if(dotResistanceMod > 100) dotResistanceMod = 100; return dotResistanceMod; } /*********************************************************** insert new hotness dot/buff stuff ****************************************************/ boolean applyBuffDotEffect(obj_id target, obj_id attacker, string type, string dot_id, long stack, int attribute, int potency, int strength, int duration, boolean verbose, string buffName) { if(!isIdValid(attacker)) { attacker = getSelf(); if(!isIdValid(attacker)) { return false; } } else { if (!isMob(target)) return false; } if (type == null) return false; if (dot_id == null) return false; if (attribute < 0 || attribute > 8) return false; if (potency != -1 && potency < 1) return false; if (strength < 1) return false; if (duration < 1) return false; if (!canApplyDotType(target, type)) { return false; } if(isIdValid(attacker) && isMob(attacker)) { addHate(target, attacker, 0.0f); addHate(attacker, target, 0.0f); } // Send out the messageTo and system message string_id old_effect_string; string_id new_effect_string; if (type.equals(DOT_FIRE)) { // Cannot get fire dots while swimming if (getState(target, STATE_SWIMMING) != 1) { old_effect_string = SID_FIRE_INCREASE; new_effect_string = SID_FIRE; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_onfire.prt", target, "", null, "state_onfire"); playClientEffectObj(target, "sound/sta_onfire_on.snd", target, ""); } else { buff.removeBuff(target, buffName); return false; } } else if (type.equals(DOT_ACID)) { old_effect_string = SID_ACID_INCREASE; new_effect_string = SID_ACID; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_acid.prt", target, "", null, "state_acid"); playClientEffectObj(target, "sound/wep_heavy_acid_launcher_hit.snd", target, ""); } else if (type.equals(DOT_ENERGY)) { old_effect_string = SID_ENERGY_INCREASE; new_effect_string = SID_ENERGY; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_energy.prt", target, "", null, "state_energy"); playClientEffectObj(target, "sound/item_electronics_break.snd", target, ""); } else if (type.equals(DOT_COLD)) { old_effect_string = SID_COLD_INCREASE; new_effect_string = SID_COLD; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_energy.prt", target, "", null, "state_cold"); playClientEffectObj(target, "sound/item_electronics_break.snd", target, ""); } else if (type.equals(DOT_ELECTRICITY)) { old_effect_string = SID_ELECTRICITY_INCREASE; new_effect_string = SID_ELECTRICITY; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_energy.prt", target, "", null, "state_electricity"); playClientEffectObj(target, "sound/item_electronics_break.snd", target, ""); } else if (type.equals(DOT_KINETIC)) { old_effect_string = SID_KINETIC_INCREASE; new_effect_string = SID_KINETIC; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_energy.prt", target, "", null, "state_kinetic"); playClientEffectObj(target, "sound/item_electronics_break.snd", target, ""); } else if (type.equals(DOT_BLEEDING)) { new_effect_string = SID_BLEEDING; old_effect_string = SID_BLEEDING_INCREASE; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_bleeding.prt", target, "spine3", null, "state_bleeding"); playClientEffectObj(target, "sound/sta_bleeding_on.snd", target, ""); } else if (type.equals(DOT_POISON)) { old_effect_string = SID_POISONED_INCREASE; new_effect_string = SID_POISONED; if(stack == 1) playClientEffectObj(target, "appearance/pt_state_poisoned.prt", target, "", null, "state_poisoned"); playClientEffectObj(target, "sound/sta_poisoned_on.snd", target, ""); } else { buff.removeBuff(target, buffName); return false; } // Attach the dot script if (!hasScript(target, SCRIPT_PLAYER_DOT)) attachScript(target, SCRIPT_PLAYER_DOT); /* Dont need this yet if(type.equals(DOT_DISEASE)) { _applyDiseaseDamage(target, dot_id); } */ // If the dot is stacking with an existing dot_id, no need to send another message. if (stack == 1) { //fingerprint the messageTo loop trial.bumpSession(target, buffName); dictionary d = trial.getSessionDict(target, buffName); d.put("buffName", buffName); d.put("caster", attacker); d.put("strength", strength); d.put("type", type); //start the damage MessageTo loop messageTo(target, "OnBuffDotPulse", d, buff.BUFF_DOT_TICK, false); } if (verbose) { if (stack == 1) combat.sendCombatSpamMessage(target, new_effect_string); else combat.sendCombatSpamMessage(target, old_effect_string); } return true; } /*********************************************************************** * @brief applies the damage of the specifed dot Based on the Buff system * * @param obj_id target * @param string dot_id * * @return boolean false on error or duration over ***********************************************************************/ boolean applyBuffDotDamage(obj_id target, obj_id caster, string buffName, int strength, string type) { if (!isIdValid(target) || !isIdValid(caster)) return false; // Absorption skill mods on the target reduce the effective strength of the dot during damage pulses. int absorption_mod = 0; int vulnerability_mod = (int)getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_all"); dictionary protDic = armor.getCombatArmorSpecialProtections(target); float resistance = 0.0f; if(isPlayer(target)) { resistance = (float)armor.getCombatArmorGeneralProtection(target); } if(type.equals(DOT_FIRE)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_fire"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_fire"); if(isPlayer(target)) { resistance += protDic.getFloat("heat"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_ACID)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_acid"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_acid"); if(isPlayer(target)) { resistance += protDic.getFloat("acid"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_COLD)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_cold"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_cold"); if(isPlayer(target)) { resistance += protDic.getFloat("cold"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_ELECTRICITY)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_electricity"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_electricity"); if(isPlayer(target)) { resistance += protDic.getFloat("electricity"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_ENERGY)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_energy"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_energy"); if(isPlayer(target)) { resistance += protDic.getFloat("energy"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_KINETIC)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_kinetic"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_kinetic"); if(isPlayer(target)) { resistance += protDic.getFloat("kinetic"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_BLEEDING)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_bleeding"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_bleed"); if(isPlayer(target)) { resistance += protDic.getFloat("cold"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else if(type.equals(DOT_POISON)) { absorption_mod += getEnhancedSkillStatisticModifier(target, "absorption_poison"); vulnerability_mod += getEnhancedSkillStatisticModifierUncapped(target, "dot_vulnerability_poison"); if(isPlayer(target)) { resistance += protDic.getFloat("acid"); } else { resistance += (float)utils.getIntScriptVar(target, armor.SCRIPTVAR_CACHED_GENERAL_PROTECTION); } //nerfing skill mod resistances absorption_mod /= MOD_DIVISOR; //We don't nerf expertise dot absorption. absorption_mod += (int)getSkillStatisticModifier(target, "expertise_dot_absorption_all"); absorption_mod += (int)(combat.convertProtectionToPercent(resistance) * DOT_ARMOR_MITIGATION_PERCENT); } else { return false; } // absorption reduces the strength of a dot by the given %. int damageAbsorbed = 0; if (absorption_mod > 0) { //cap the amount you can reduce a DoT by by 50% if (absorption_mod > 50) absorption_mod = 50; damageAbsorbed = (int)(strength * (absorption_mod / 100.0f)); strength = (int)(strength * (1.0f - (absorption_mod / 100.0f))); } if (vulnerability_mod > 0) { strength = (int)(strength * (1.0f + (vulnerability_mod / 100.0f))); } // Bring over the generic damage multiply/divisor from combat base to apply to dot damage. int expertiseDamageBonus = getEnhancedSkillStatisticModifierUncapped(caster, "combat_multiply_damage_dealt"); expertiseDamageBonus += getEnhancedSkillStatisticModifierUncapped(target, "combat_multiply_damage_taken"); float tempDamageFloat = (float)strength; tempDamageFloat = tempDamageFloat * (1.0f + ((float)expertiseDamageBonus / 100.0f) ); int expertiseDamageReduction = getEnhancedSkillStatisticModifierUncapped(caster, "combat_divide_damage_dealt"); expertiseDamageReduction += getEnhancedSkillStatisticModifierUncapped(target, "combat_divide_damage_taken"); expertiseDamageReduction = expertiseDamageReduction > 100 ? 100 : expertiseDamageReduction; tempDamageFloat = tempDamageFloat * (1.0f - ((float)expertiseDamageReduction / 100.0f)); strength = (int)tempDamageFloat; // Dots don't incap. Reduce strength to one less than the current attribute if necessary. int current_attrib = getAttrib(target, HEALTH); // If a player was hit by a dot at one point and was attackable, but now is not, the dot should be removed. if( (caster != target) && !pvpCanAttack(caster, target)) { buff.removeBuff(target, buffName); return false; } string mitigationString = "("+damageAbsorbed + getString(new string_id("dot_message", "generic_absorbed_buff"))+")"; if(strength > 0) { hit_result hit = new hit_result(); hit.damage = strength; hit.success = true; string_id strSpam = new string_id("combat_effects", "damage_fly"); prose_package ppFly = new prose_package(); ppFly = prose.setStringId(ppFly, strSpam); ppFly = prose.setDI(ppFly, -strength); prose_package ppSpam = new prose_package(); if (type.equals(DOT_FIRE)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_FIRE_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, caster, ppFly, 1f, colors.FIREBRICK, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_FIRE_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.FIREBRICK, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(DOT_ACID)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_ACID_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, caster, ppFly, 1f, colors.OLIVEDRAB, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_ACID_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.OLIVEDRAB, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(DOT_ENERGY)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_ENERGY_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, caster, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_ENERGY_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(DOT_COLD)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_COLD_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, caster, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_COLD_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(DOT_ELECTRICITY)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_ELECTRICITY_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, caster, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_ELECTRICITY_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } } else if (type.equals(DOT_KINETIC)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_KINETIC_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, caster, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_KINETIC_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target, target, ppFly, 1f, colors.DEEPSKYBLUE, FLY_TEXT_FLAG_IS_DOT); } } else if(type.equals(dot.DOT_BLEEDING)) { // Track damage for xp calcs if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_BLEED_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,caster,ppFly, 1f, colors.INDIANRED, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_BLEED_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,target,ppFly, 1f, colors.INDIANRED, FLY_TEXT_FLAG_IS_DOT); } } else if(type.equals(dot.DOT_POISON)) { if (isIdValid(caster) && !isDead(caster)) { ppSpam = prose.setStringId(ppSpam, SID_POISON_DMG_ATKR); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setTO(ppSpam, caster); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(caster, target, ppSpam, true, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,caster,ppFly, 1f, colors.YELLOWGREEN, FLY_TEXT_FLAG_IS_DOT); } else { ppSpam = prose.setStringId(ppSpam, SID_POISON_DMG); ppSpam = prose.setTT(ppSpam, target); ppSpam = prose.setDI(ppSpam, strength); ppSpam = prose.setTU(ppSpam, mitigationString); sendCombatSpamMessageProse(target, target, ppSpam, false, true, true, COMBAT_RESULT_DEBUFF); showFlyTextPrivateProseWithFlags(target,target,ppFly, 1f, colors.YELLOWGREEN, FLY_TEXT_FLAG_IS_DOT); } } else { return false; } doDamage(caster, target, hit); if(isIdValid(caster) && isIdValid(target) && exists(caster) && exists(target)) { startCombat(caster, target); startCombat(target, caster); } // Track damage for xp calcs if(isIdValid(caster) && !isDead(caster)) { //try to assign xp based on weapon used obj_id myWeapon = getCurrentWeapon(caster); if(isIdValid(myWeapon)) xp.updateCombatXpList(target, caster, myWeapon, strength); else //since the type no longer matters, we will give rifle. If we gave general we wouldnt be giving full credit. xp.updateCombatXpList(target, caster, xp.COMBAT_RANGEDSPECIALIZE_RIFLE, strength); } else { xp.updateCombatXpList(target, target, xp.PERMISSIONS_ONLY, strength); } if(!isPlayer(target)) { if(isIdValid(caster) && exists(caster)) { addHate(target, caster, strength); addHate(caster, target, 0.0f); } } } return true; } boolean removeBuffDotEffect(obj_id target, string type, boolean verbose) { ////LOG("LOG_CHANNEL", "dot::removeDotEffect -- " + dot_id); if (!isIdValid(target)) { //LOG("LOG_CHANNEL", "dot::removeDotEffect -- target is null"); return false; } int[] dotBuffs = buff.getAllBuffsByEffect(target, "dot"); if(dotBuffs == null || dotBuffs.length <= 0) { string[] dots = getAllDots(target); if(dots == null && hasScript(target, SCRIPT_PLAYER_DOT)) detachScript(target, SCRIPT_PLAYER_DOT); } // Check to see if there are any dots of the given type left. If not, send a message. if (type.equals(DOT_FIRE)) { if (verbose) combat.sendCombatSpamMessage(target, SID_FIRE_STOP); setState(target, STATE_ON_FIRE, false); stopClientEffectObjByLabel(target, "state_onfire"); playClientEffectObj(target, "sound/sta_onfire_off.snd", target, ""); } else if (type.equals(DOT_ACID)) { if (verbose) combat.sendCombatSpamMessage(target, SID_ACID_STOP); stopClientEffectObjByLabel(target, "state_acid"); } else if (type.equals(DOT_ENERGY)) { if (verbose) combat.sendCombatSpamMessage(target, SID_ENERGY_STOP); stopClientEffectObjByLabel(target, "state_energy"); } else if (type.equals(DOT_COLD)) { if (verbose) combat.sendCombatSpamMessage(target, SID_COLD_STOP); stopClientEffectObjByLabel(target, "state_cold"); } else if (type.equals(DOT_ELECTRICITY)) { if (verbose) combat.sendCombatSpamMessage(target, SID_ELECTRICITY_STOP); stopClientEffectObjByLabel(target, "state_electricity"); } else if (type.equals(DOT_KINETIC)) { if (verbose) combat.sendCombatSpamMessage(target, SID_ELECTRICITY_STOP); stopClientEffectObjByLabel(target, "state_kinetic"); } else if (type.equals(DOT_POISON)) { if (verbose) combat.sendCombatSpamMessage(target, SID_POISONED_STOP); stopClientEffectObjByLabel(target, "state_poisoned"); } else if (type.equals(DOT_BLEEDING)) { if (verbose) combat.sendCombatSpamMessage(target, SID_BLEEDING_STOP); stopClientEffectObjByLabel(target, "state_bleeding"); } return true; }