Files
dsrc/sku.0/sys.server/compiled/game/script/library/healing.scriptlib
T
2013-09-10 23:17:15 -07:00

5737 lines
153 KiB
Plaintext

/**
* Copyright (c)2000-2002 Sony Online Entertainment Inc.
* All Rights Reserved
*
* Title: healing.scriptlib
* Description: base functions for healing & wound curing
* @author $Author:$
* @version $Revision:$
*/
/***** INCLUDES ********************************************************/
include ai.ai_combat;
include library.ai_lib;
include library.buff;
include library.camping;
include library.combat;
include library.combat;
include library.consumable;
include library.cybernetic;
include library.dot;
include library.factions;
include library.group;
include library.luck;
include library.metrics;
include library.pet_lib;
include library.player_structure;
include library.prose;
include library.pvp;
include library.stealth;
include library.sui;
include library.utils;
include library.vehicle;
include library.xp;
include library.beast_lib;
/***** CONSTANTS *******************************************************/
const int VAR_ITEM_REUSE_TIME = 20;
const int ITEM_CHANNEL_HEAL_TICKS = 5;
const string VAR_ENHANCER_EFFICIENCY = "healing.enhancement";
const string VAR_ITEM_POWER = "healing.power";
const string VAR_ITEM_TIMER = "healing.item.timer";
const string VAR_PLAYER_HOT_ID = "healing.hot_id";
const string MSG_HEAL_OVER_TIME = "handleHealOverTimeTick";
const string_id SID_ITEM_TOO_SOON = new string_id("healing", "item_too_soon");
const string_id SID_ITEM_NOT_A_PET = new string_id("healing", "item_not_a_pet");
const string_id SID_ITEM_NOT_YOUR_PET = new string_id("healing", "item_not_your_pet");
const string_id SID_ITEM_NO_DAMAGE = new string_id("healing", "item_no_damage");
const string_id SID_ITEM_PLAYER_HEAL = new string_id("healing", "item_player_heal");
const string_id SID_ITEM_PET_HEAL = new string_id("healing", "item_pet_heal");
const string_id SID_BEAST_MASTER_HEAL = new string_id("healing", "beast_master_heal");
const string_id SID_PERFORM_HEAL_DAMAGE_SUCCESS = new string_id("healing", "perform_heal_damage_success");
const string_id SID_PERFORM_HEAL_WOUND_SUCCESS = new string_id("healing", "perform_heal_wound_success");
const string_id SID_PERFORM_REVIVE_SUCCESS = new string_id("healing", "perform_revive_success");
const string_id SID_PERFORM_REVIVE_GROGGINESS = new string_id("healing", "perform_revive_grogginess");
const string_id SID_PERFORM_REVIVE_TOO_LONG = new string_id("healing", "perform_revive_too_long");
const string_id SID_PERFORM_REVIVE_JEDI_CONSENT = new string_id("healing", "perform_revive_jedi_consent");
const string_id SID_PERFORM_REVIVE_CONSENT = new string_id("healing", "perform_revive_consent");
const string_id SID_PERFORM_CURE_STATE_FAIL = new string_id("healing", "perform_cure_state_fail");
const string_id SID_PERFORM_BUFF_FAIL = new string_id("healing", "perform_buff_fail");
const string_id SID_PERFORM_DEBUFF_FAIL = new string_id("healing", "perform_debuff_fail");
const string_id SID_PERFORM_HOT_FAIL = new string_id("healing", "perform_hot_fail");
//ATTRIB_MOD (AM) ATTACK CONSTANTS
const float AM_HEAL_WOUND = -1.0f;
const float AM_HEAL_SHOCK = -2.0f;
const float AM_ADD_SHOCK = -3.0f;
// POSSIBLE DEPRICATED CONSTANTS
const float HEARTBEAT_PERFORMANCE = 6.0f;
const int OBSERVERS_MAX = 20;
const int VAR_HEALDAMAGE_ROUNDTIME = 10;
const float VAR_HEALDAMAGE_ROUNDTIME_CAP = 3.0f;
const int VAR_HEALWOUND_ROUNDTIME = 10;
const int VAR_HEALENHANCE_ROUNDTIME = 30;
const float VAR_SURGICAL_DROID_RANGE = 20.0f;
const int VAR_MAX_BUFF_TIME = 7200;
const float VAR_BUFF_MOD_ATTACK = 10.0f;
const float VAR_BUFF_MOD_DECAY = 10.0f;
const int VAR_HEALDAMAGE_COST = 100;
const int VAR_HEALWOUND_COST = 250;
const int VAR_HEALSTATE_COST = 150;
const int VAR_HEALENHANCE_COST = 250;
const int VAR_FIRSTAID_COST = 125;
const int VAR_CURE_POISON_COST = 200;
const int VAR_CURE_FIRE_COST = 350;
const int VAR_CURE_DISEASE_COST = 200;
const int VAR_APPLY_POISON_COST = 150;
const int VAR_APPLY_DISEASE_COST = 150;
const int VAR_QUICK_HEAL_COST = 500;
const int VAR_TEND_WOUND_COST = 500;
const int VAR_TEND_DAMAGE_COST = 250;
const int VAR_QUICK_HEAL_WOUND_COST = 10;
const int VAR_QUICK_HEAL_BASE_POWER = 400;
const int VAR_TEND_WOUND_WOUND_COST = 7;
const int VAR_TEND_WOUND_BASE_POWER = 15;
const int VAR_TEND_DAMAGE_WOUND_COST = 5;
const int VAR_TEND_DAMAGE_BASE_POWER = 75;
const int VAR_HEAL_MIND_COST = 100;
const int VAR_HEAL_MIND_WOUND_COST = 40;
const int VAR_HEAL_MIND_BASE_POWER = 500;
const float VAR_EFFECT_DISPLAY_RADIUS = 45.0f;
const float VAR_STIMPACK_DROID_RADIUS = 30.0f;
const int VAR_AUTO_REPAIR_PULSE_INTERVAL = 10;
const int VAR_AUTO_REPAIR_MIN_INTERVAL = 2;
const int COST_MIND_REVIVE = 500;
const int REVIVE_TIMER = 1800;
const float HEALING_KILL_CREDIT_MULTIPLIER = 0.1f;
const float HEALING_AGGRO_REDUCER = 10.0f;
const float HEAL_OVER_TIME_AGGRO_REDUCER = 0.5f;
const string VAR_OBSERVER_BASE = "performance";
const string VAR_OBSERVER_LIST = "performance.observer_ids";
const string VAR_OBSERVER_BOX = "performance.observer_listbox_pId";
const string VAR_OBSERVER_SKILLCHECK = "performance.skill_check";
const string VAR_PERFORMANCE_HAS_DANCE_BUFF = "performance.has_dance_buff";
const string VAR_PERFORMANCE_HAS_MUSIC_BUFF = "performance.has_music_buff";
const string VAR_HEALING_CAN_HEALDAMAGE = "healing.can_heal_damage";
const string VAR_HEALING_CAN_HEALWOUND = "healing.can_heal_wound";
const string VAR_HEALING_RANGE = "healing.range";
const string VAR_HEALING_AREA = "healing.area";
const string VAR_HEALING_STATE = "healing.state";
const string VAR_HEALING_CURE_DOT = "healing.cure_dot";
const string VAR_HEALING_APPLY_DOT = "healing.apply_dot";
const string VAR_HEALING_DOT_POWER = "healing.dot_power";
const string VAR_HEALING_DOT_POTENCY = "healing.dot_potency";
const string VAR_HEALING_DOT_ID = "healing.dot_id";
const string VAR_HEALING_DOT_ATTRIBUTE = "healing.dot_attribute";
const string VAR_HEALING_DOT_DURATION = "healing.dot_duration";
const string VAR_HEALING_ABSORPTION = "healing.absorption";
const string SCRIPT_VAR_MEDICINE_BUFF = "healing.medicine_buff";
const string SCRIPT_VAR_MEDICINE_REBUFF = "healing.medicine_rebuff";
const string SCRIPT_VAR_DANCE_MIND_BUFF = "healing.dance_mind_buff";
const string SCRIPT_VAR_DANCE_MIND_BUFF_TIME = "healing.dance_mind_buff_time";
const string SCRIPT_VAR_MUSIC_MIND_BUFF = "healing.music_mind_buff";
const string SCRIPT_VAR_MUSIC_MIND_BUFF_TIME = "healing.music_mind_buff_time";
const string SCRIPT_VAR_RANGED_MED = "healing.ranged_med";
const string SCRIPT_VAR_DAMAGE_MED = "healing.damage_med";
const string LISTBOX_LIST = "lstList";
const string LISTBOX_DATA = "dataList";
const string_id UI_OBSERVE = new string_id("ui","observe");
const string_id UI_STOP_OBSERVING = new string_id("ui","stop_observing");
//HEALING TYPES
const string HEAL_TYPE_MEDICAL_DAMAGE = "medical_damage";
const string HEAL_TYPE_MEDICAL_WOUND = "medical_wound";
const string HEAL_TYPE_MEDICAL_STATE = "medical_state";
const string HEAL_TYPE_MEDICAL_BUFF = "medical_buff";
const string HEAL_TYPE_MEDICAL_REVIVE = "medical_revive";
const string HEAL_TYPE_MEDICAL_FIRSTAID = "medical_firstaid";
const string HEAL_TYPE_MEDICAL_CURE_POISON = "medical_cure_poison";
const string HEAL_TYPE_MEDICAL_CURE_DISEASE = "medical_cure_disease";
const string HEAL_TYPE_MEDICAL_CURE_FIRE = "medical_cure_fire";
const string HEAL_TYPE_MEDICAL_APPLY_POISON = "medical_apply_poison";
const string HEAL_TYPE_MEDICAL_APPLY_DISEASE = "medical_apply_disease";
const string HEAL_TYPE_MEDICAL_QUICK_HEAL = "medical_quick_heal";
const string HEAL_TYPE_MEDICAL_TEND_WOUND = "medical_tend_wound";
const string HEAL_TYPE_MEDICAL_TEND_DAMAGE = "medical_tend_damage";
const string HEAL_TYPE_MEDICAL_HEAL_MIND = "medical_heal_mind";
const string HEAL_TYPE_DANCE_WOUND = "dance_wound";
const string HEAL_TYPE_DANCE_SHOCK = "dance_shock";
const string HEAL_TYPE_DANCE_MIND_BUFF = "dance_mind_buff";
const string HEAL_TYPE_MUSIC_WOUND = "music_wound";
const string HEAL_TYPE_MUSIC_SHOCK = "music_shock";
const string HEAL_TYPE_MUSIC_MIND_BUFF = "music_mind_buff";
const string HEAL_TYPE_JUGGLE_WOUND = "juggle_wound";
const string HEAL_TYPE_JUGGLE_SHOCK = "juggle_shock";
const string HEAL_TYPE_JUGGLE_MIND_BUFF = "juggle_mind_buff";
//SCRIPT CONSTANTS
const string SCRIPT_DANCE = "systems.healing.healing_dance";
const string SCRIPT_MUSIC = "systems.healing.healing_music";
const string SCRIPT_JUGGLE = "systems.healing.healing_juggle";
const string SCRIPT_MEDIC = "systems.healing.healing_medic";
const string SCRIPT_XENOBIOLOGY = "systems.healing.healing_xenobiology";
const string_id SID_NOT_ENOUGH_MIND = new string_id("healing", "not_enough_mind");
const string_id SID_APPLY_POISON_SELF = new string_id("healing", "apply_poison_self");
const string_id SID_APPLY_POISON_OTHER = new string_id("healing", "apply_poison_other");
const string_id SID_APPLY_DISEASE_SELF = new string_id("healing", "apply_disease_self");
const string_id SID_APPLY_DISEASE_OTHER = new string_id("healing", "apply_disease_other");
const string_id SID_RESIST_DOT_OTHER = new string_id("healing", "dot_resist_other");
const string_id SID_MIND_TOO_DRAINED = new string_id("healing", "mind_too_drained");
const string_id SID_YOU_APPLY_FIRST_AID = new string_id("healing", "you_apply_first_aid");
const string_id SID_APPLIES_FIRST_AID = new string_id("healing", "applies_first_aid");
const string_id SID_APPLY_FIRST_AID_SELF = new string_id("healing", "apply_first_aid_self");
const string_id SID_APPLY_POISON_ANTIDOTE = new string_id("healing", "apply_poison_antidote");
const string_id SID_APPLIES_POISON_ANTIDOTE = new string_id("healing", "applies_poison_antidote");
const string_id SID_APPLY_POISON_ANTIDOTE_SELF = new string_id("healing", "apply_poison_antidote_self");
const string_id SID_ATTEMPT_SUPPRESS_FLAMES = new string_id("healing", "attempt_suppress_flames");
const string_id SID_COVERS_YOU_BLANKET = new string_id("healing", "covers_you_blanket");
const string_id SID_COVERS_BLANKET_SELF = new string_id("healing", "cover_blanket_self");
const string_id SID_APPLY_DISEASE_ANTIDOTE = new string_id("healing", "apply_disease_antidote");
const string_id SID_APPLIES_DISEASE_ANTIDOTE = new string_id("healing", "applies_disease_antidote");
const string_id SID_APPLY_DISEASE_ANTIDOTE_SELF = new string_id("healing", "apply_disease_antidote_self");
const string_id SID_CANNOT_RESUS_WITHOUT_KIT = new string_id("healing", "cannot_resus_without_kit");
const string_id SID_CANNOT_RESUS_WITHOUT_TARGET = new string_id("healing", "cannot_resus_without_target");
const string_id SID_CANNOT_RESUS_WITHOUT_PACK = new string_id("healing", "cannot_resus_without_pack");
const string_id SID_TARGET_DEAD_TOO_LONG = new string_id("healing", "target_dead_too_long");
const string_id SID_MUST_HAVE_JEDI_CONSENT = new string_id("healing", "must_have_jedi_consent");
const string_id SID_GROUP_OR_CONSENT_FROM_TARGET = new string_id("healing", "group_or_consent_from_target");
const string_id SID_TEND_WOUNDS_INVALID_TARGET = new string_id("healing", "tend_wounds_invalid_target");
const string_id SID_CANNOT_DO_THAT_TIME = new string_id("healing", "cannot_do_that_time");
const string_id SID_YOU_MUST_WAIT = new string_id("healing", "you_must_wait");
const string_id SID_CANT_HEAL_DAMAGE_OR_STATES = new string_id("healing", "cant_heal_damage_or_states");
const string_id SID_MUST_BE_IN_HOSPITAL_OR_CS = new string_id("healing", "must_be_in_hospital_or_cs");
const string_id SID_MUST_BE_IN_HOSP_OR_CS_OR_DROID = new string_id("healing", "must_be_in_hosp_or_cs_or_droid");
const string_id SID_MUST_WAIT_TO_HEAL_OR_ENHANCE = new string_id("healing", "must_wait_to_heal_or_enhance");
const string_id SID_NO_HEAL_OR_ENHANCE_ABILITY = new string_id("healing", "no_heal_or_enchance_ability");
const string_id SID_NO_WOUNDS_OF_TYPE_SELF = new string_id("healing", "no_wounds_of_type_self");
const string_id SID_NO_WOUNDS_OF_TYPE_TARGET = new string_id("healing", "no_wounds_of_type_target");
const string_id SID_REMOVE_STATE_FROM_TARGET = new string_id("healing", "remove_state_from_target");
const string_id SID_REMOVE_STATE_FROM_YOU = new string_id("healing", "remove_state_from_you");
const string_id SID_REMOVE_STATE_SELF = new string_id("healing", "remove_state_self");
const string_id SID_YOU_ENHANCE_YOUR_ATT = new string_id("healing", "you_enhance_your_att");
const string_id SID_YOU_ENHANCE_TARGETS_ATTRIBUTE = new string_id("healing", "you_enchance_targets_attribute");
const string_id SID_MEDIC_ENHANCES_YOUR_ATTRIBUTE = new string_id("healing", "medic_enchances_your_attribute");
const string_id SID_REAPPLY_ENHANCEMENT_TARGET = new string_id("healing", "reapply_enhancement_target");
const string_id SID_REAPPLIES_ENHANCEMENT_YOU = new string_id("healing", "reapplies_enhancement_you");
const string_id SID_REAPPLY_ENHANCEMENT_SELF = new string_id("healing", "reapply_enhancement_self");
const string_id SID_ENHANCE_ATTRIBUTE_BY_SELF = new string_id("healing", "enhance_attribute_by_self");
const string_id SID_PVP_NO_HELP = new string_id("healing", "pvp_no_help");
const string_id SID_HEAL_ATTRIBUTE_TARGET = new string_id("healing", "heal_attribute_target");
const string_id SID_ATTRIBUTE_HEALED = new string_id("healing", "attribute_healed");
const string_id SID_HEAL_ATTRIB_SELF = new string_id("healing", "heal_attrib_self");
const string_id SID_DROID_REPAIR_WOUND_SELF = new string_id("healing", "droid_repair_wound_self");
const string_id SID_DROID_REPAIR_WOUND_OTHER = new string_id("healing", "droid_repair_wound_other");
const string_id SID_DROID_REPAIR_DAMAGE_SELF = new string_id("healing", "droid_repair_damage_self");
const string_id SID_DROID_REPAIR_DAMAGE_OTHER = new string_id("healing", "droid_repair_damage_other");
const string RESPONSE_TEXT = "datatables/healing/healing_response.iff";
const string PP_FILE_LOC = "healing_response";
const int[] COMBAT_STATES = { STATE_DIZZY,
STATE_BLINDED,
STATE_STUNNED,
STATE_INTIMIDATED };
const string_id[] SID_PERFORM_CURE_STATE_SUCCESS = { new string_id("healing", "perform_cure_state_dizzy_success"),
new string_id("healing", "perform_cure_state_blinded_success"),
new string_id("healing", "perform_cure_state_stunned_success"),
new string_id("healing", "perform_cure_state_intimidated_success") };
const string[] ATTRIBUTES =
{
"HEALTH",
"CONSTITUTION",
"ACTION",
"STAMINA",
"MIND",
"WILLPOWER"
};
boolean performHealDamage(attacker_data attackerData, defender_data[] defenderData, combat_data action_data)
{
if((action_data.dotIntensity > 0) && (action_data.dotDuration > 0))
return performHealOverTime(attackerData, defenderData, action_data);
obj_id medic = attackerData.id;
int toHeal = action_data.addedDamage;
int totalDelta = 0;
boolean total_success = false;
toHeal = getExpertiseModifiedHealing(medic, toHeal, action_data);
// Work around until we get some animation issues corrected.
string actionName = action_data.actionName;
boolean useTempParticle = false;
boolean playParticleOnMedic = false;
if(actionName.startsWith("me_bacta_bomb") || actionName.startsWith("me_bacta_grenade") )
useTempParticle = true;
if(actionName.startsWith("sp_cloaked_recovery"))
{
playParticleOnMedic = true;
}
for(int i = 0; i < defenderData.length; i++)
{
if(!isIdValid(defenderData[i].id) || !exists(defenderData[i].id) || !isMob(defenderData[i].id) ||
isDead(defenderData[i].id))
{
continue;
}
if(!isValidHealTarget(medic, defenderData[i].id))
{
continue;
}
toHeal = getHealingAfterReductions(medic, defenderData[i].id, toHeal);
toHeal = getTargetHealingBonus(medic, defenderData[i].id, toHeal);
if(luck.isLucky(defenderData[i].id, 0.005f))
{
float bonus = toHeal * 0.2f;
if(bonus < 1)
bonus = 1;
toHeal += bonus;
}
int hBefore = getAttrib(defenderData[i].id, action_data.attribute);
boolean success = healDamage(defenderData[i].id, action_data.attribute, toHeal);
if(success)
{
int delta = getAttrib(defenderData[i].id, action_data.attribute) - hBefore;
if(delta <= 0)
{
continue;
}
totalDelta += delta;
prose_package pp = new prose_package();
pp = prose.setStringId(pp, SID_PERFORM_HEAL_DAMAGE_SUCCESS);
pp = prose.setTT(pp, medic);
pp = prose.setTO(pp, defenderData[i].id);
pp = prose.setDI(pp, delta);
sendMedicalSpam(medic, defenderData[i].id, pp, true, true, true, COMBAT_RESULT_MEDICAL);
pp = prose.setStringId(pp, new string_id("healing", "heal_fly"));
pp = prose.setDI(pp, delta);
pp = prose.setTO(pp, ATTRIBUTES[action_data.attribute]);
showFlyTextPrivateProseWithFlags(defenderData[i].id, defenderData[i].id, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
if(medic != defenderData[i].id)
showFlyTextPrivateProseWithFlags(defenderData[i].id, medic, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
float hateMod = action_data.hateDamageModifier;
int healingAgroMod = getEnhancedSkillStatisticModifierUncapped(medic, "expertise_agro_healing");
float agroReductionFact = 1.0f - ((float)healingAgroMod/100.0f);
float modifiedHate = (delta * agroReductionFact) /HEALING_AGGRO_REDUCER;
if (isPlayer(medic))
_addMedicalHate(medic, defenderData[i].id, (int)modifiedHate, hateMod);
pvpHelpPerformed(medic, defenderData[i].id);
//possible buff application for medic and/or defender
applyDefenderHealBuffs(medic, defenderData[i].id, action_data);
applyMedicHealBuffs(medic, action_data);
location loc = getLocation(defenderData[i].id);
if(useTempParticle)
{
obj_id[] players = getAllPlayers(loc, 64);
if(players != null)
{
for(int j = 0; j < players.length; j++)
{
if(stealth.hasInvisibleBuff(players[j]))
continue;
if(actionName.startsWith("me_bacta_bomb") )
playClientEffectLoc(players[j], "clienteffect/bacta_bomb.cef" , loc, 0);
if(actionName.startsWith("me_bacta_grenade") )
playClientEffectLoc(players[j], "clienteffect/bacta_grenade.cef" , loc, 0);
}
}
}
else if(playParticleOnMedic)
{
if(!stealth.hasInvisibleBuff(medic))
playClientEffectObj(medic, "appearance/pt_heal.prt", medic, "");
}
else
{
if(!stealth.hasInvisibleBuff(defenderData[i].id))
playHealDamageEffect(loc);
}
if (delta == 0 && actionName.indexOf("_sh_") > -1)
{
CustomerServiceLog("Heal-Fail", "%TU received a success from heal damage but healed for a delta of 0 on heal: "+actionName, medic);
}
}
total_success |= success;
}
// A healing ability has not succeeded, if no healing was performed. Heal Over Time abilities do not reach this point.
if(totalDelta <= 0)
{
return false;
}
pvp.bfCreditForHealing(medic, totalDelta);
return total_success;
}
boolean applyDefenderHealBuffs(obj_id medic, obj_id defender, combat_data actionData)
{
string actionName = actionData.actionName;
string buffName = actionData.buffNameTarget;
float buffStrength = actionData.buffStrengthTarget;
float buffDuration = actionData.buffDurationTarget;
if (buffName == null || buffName.equals(""))
return false;
if(!combat.expertiseRandomBuffChance(medic, actionData))
return false;
if(!isValidHealTarget(defender))
return false;
buffDuration = combat.getExpertiseBuffDurationMods(medic, actionData, buffName, buffDuration);
combat.combatLog(medic, defender, "applyDefenderHealBuffs", "Applying defender buff - " + buffName);
return buff.applyBuff(defender, buffName, buffDuration, buffStrength);
}
boolean applyMedicHealBuffs(obj_id medic, combat_data actionData)
{
string actionName = actionData.actionName;
string buffName = actionData.buffNameSelf;
float buffStrength = actionData.buffStrengthSelf;
float buffDuration = actionData.buffDurationSelf;
if (buffName == null || buffName.equals(""))
return false;
if(!combat.expertiseRandomBuffChance(medic, actionData))
return false;
buffDuration = combat.getExpertiseBuffDurationMods(medic, actionData, buffName, buffDuration);
combat.combatLog(medic, null, "applyMedicHealBuffs", "Applying medic buff - " + buffName);
return buff.applyBuff(medic, buffName, buffDuration, buffStrength);
}
boolean performHealOverTime(attacker_data attackerData, defender_data[] defenderData, combat_data action_data)
{
obj_id medic = attackerData.id;
int maxHeal = action_data.addedDamage;
int duration = action_data.dotDuration;
int perTick = action_data.dotIntensity;
string specialLine = action_data.specialLine;
duration += getEnhancedSkillStatisticModifierUncapped(medic, "expertise_hot_duration_" + specialLine);
perTick = getExpertiseModifiedHealing(medic, perTick, action_data);
maxHeal = getExpertiseModifiedHealing(medic, maxHeal, action_data);
int tickLength = (int)(((float)duration) / (((float)maxHeal) / ((float)perTick)));
for(int i = 0; i < defenderData.length; i++)
{
if(isDead(defenderData[i].id) || !isValidHealTarget(defenderData[i].id))
continue;
perTick = getHealingAfterReductions(medic, defenderData[i].id, perTick);
perTick = getTargetHealingBonus(medic, defenderData[i].id, perTick);
startHealOverTime(medic, defenderData[i].id, action_data.actionName, duration, tickLength, perTick, true);
pvpHelpPerformed(medic, defenderData[i].id);
location loc = getLocation(defenderData[i].id);
playHealDamageEffect(loc);
}
return true;
}
int getExpertiseModifiedHealing(obj_id medic, int toHeal, combat_data action_data)
{
string specialLine = action_data.specialLine;
float expertiseHealingBonus = 0.0f;
expertiseHealingBonus += getEnhancedSkillStatisticModifierUncapped(medic, "expertise_healing_all");
if(specialLine != null && specialLine != "")
expertiseHealingBonus += getEnhancedSkillStatisticModifierUncapped(medic, "expertise_healing_line_" + specialLine);
float toHealFloat = toHeal;
toHealFloat = toHealFloat * (1 + (expertiseHealingBonus/100) );
toHeal = (int)toHealFloat;
return toHeal;
}
int getHealingAfterReductions(obj_id medic, obj_id target, int toHeal)
{
int healingReduction = getEnhancedSkillStatisticModifierUncapped(target, "expertise_healing_reduction");
float redux = (float)healingReduction / ((float)healingReduction + 50.0f);
toHeal = (int)((float)toHeal - ((float)toHeal * redux));
return toHeal;
}
int getTargetHealingBonus(obj_id medic, obj_id target, int toHeal)
{
int healingBonus = getEnhancedSkillStatisticModifierUncapped(target, "expertise_target_healing_bonus");
toHeal = (int)((float)toHeal * (1.0f + ((float)healingBonus / 100.0f)));
return toHeal;
}
/*******************************************************************************************************
*******************************************************************************************************/
boolean canUseAbility(obj_id medic, combat_data actionData)
{
return true;
}
boolean useHealDamageItem(obj_id user, obj_id item)
{
return useHealDamageItem(user, user, item);
}
boolean useHealDamageItem(obj_id user, obj_id item, int attrib)
{
return useHealDamageItem(user, user, item, attrib);
}
boolean useHealDamageItem(obj_id user, obj_id target, obj_id item)
{
return useHealDamageItem(user, target, item, HEALTH);
}
boolean useHealDamageItem(obj_id user, obj_id target, obj_id item, int attrib)
{
if(!isIdValid(target) || !isIdValid(user))
return false;
if(!isIdValid(item))
return false;
if(!isDamaged(target, attrib))
{
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("healing", "no_damage_fly"));
showFlyTextPrivateProseWithFlags(user, user, pp, 1.5f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
sendMedicalSpam(user, SID_ITEM_NO_DAMAGE, COMBAT_RESULT_MEDICAL);
return false;
}
if(!isValidHealTarget(target))
{
return false;
}
if(utils.hasScriptVar(target, VAR_ITEM_TIMER))
{
int reuseTime = utils.getIntScriptVar(target, VAR_ITEM_TIMER);
if(reuseTime > getGameTime())
{
int time_left = reuseTime - getGameTime();
//prose_package ppFly = new prose_package();
//ppFly = prose.setStringId(ppFly, new string_id("healing", "item_too_soon"));
//showFlyTextPrivateProseWithFlags(user, user, ppFly, 1.5f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, SID_ITEM_TOO_SOON);
pp = prose.setDI(pp, time_left);
sendMedicalSpam(user, pp, COMBAT_RESULT_MEDICAL);
showFlyTextPrivateProseWithFlags(user, user, pp, 1.5f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
return false;
}
utils.removeScriptVar(target, VAR_ITEM_TIMER);
}
if(!hasObjVar(item, VAR_ITEM_POWER))
return false;
int toHeal = getIntObjVar(item, VAR_ITEM_POWER);
if(luck.isLucky(target, 0.005f))
{
float bonus = toHeal * 0.2f;
if(bonus < 1)
bonus = 1;
toHeal += bonus;
}
int delta = healDamage(user, target, attrib, toHeal);
if(delta > 0)
{
decrementCount(item);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("healing", "heal_fly"));
pp = prose.setDI(pp, delta);
pp = prose.setTO(pp, ATTRIBUTES[attrib]);
showFlyTextPrivateProseWithFlags(user, user, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
pp = prose.setStringId(pp, SID_ITEM_PLAYER_HEAL);
pp = prose.setDI(pp, delta);
pp = prose.setTT(pp, target);
sendMedicalSpam(user, pp, COMBAT_RESULT_MEDICAL);
int reuseTime = VAR_ITEM_REUSE_TIME;
utils.setScriptVar(target, VAR_ITEM_TIMER, (getGameTime() + (reuseTime)));
sendCooldownGroupTimingOnly(user, ##"healItem", reuseTime);
doHealingAnimationAndEffect(user, target);
}
return (delta > 0);
}
boolean useChannelHealItem(obj_id user, obj_id item)
{
return useChannelHealItem(user, item, HEALTH);
}
boolean useChannelHealItem(obj_id user, obj_id item, int attrib)
{
if( !isIdValid(user))
return false;
if(!isIdValid(item))
return false;
//if you are not damaged, then you dont need to use this.
if(!isDamaged(user, attrib))
{
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("healing", "no_damage_fly"));
showFlyTextPrivateProseWithFlags(user, user, pp, 1.5f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
sendMedicalSpam(user, SID_ITEM_NO_DAMAGE, COMBAT_RESULT_MEDICAL);
return false;
}
//we need that objvar to determine how much power to give.
if(!hasObjVar(item, VAR_ITEM_POWER))
return false;
//get total heal amount
int toHeal = getIntObjVar(item, VAR_ITEM_POWER);
//devide total heal amount by number of ticks
int healPerTick = toHeal / ITEM_CHANNEL_HEAL_TICKS; //this is the number of ticks this stimpack will go thru
//set tick count to 0, as this is the first tick
int tick = 0;
//get location of where channel starts
location currentLoc = getLocation(user);
//Put all relevant variables in dictionary so we can pass it on
dictionary dict = new dictionary();
dict.put("user", user);
dict.put("tick", tick);
dict.put("item", item);
dict.put("healPerTick", healPerTick);
dict.put("healLoc", currentLoc);
dict.put("attrib", attrib);
//debugSpeakMsg(user, "Sending first message");
messageTo( user, "channelHeal", dict, 0, false);
//apply de-buff disabling use of stimpack again for short period of time.
buff.applyBuff(user, "recent_heal");
//item has been used, decrement count
decrementCount(item);
return true;
}
boolean useHealPetItem(obj_id user, obj_id pet, obj_id item)
{
if(!isIdValid(user))
return false;
if(!isIdValid(pet))
return false;
if(!isIdValid(item))
return false;
if(!pet_lib.isCreaturePet(pet))
{
sendMedicalSpam(user, SID_ITEM_NOT_A_PET, COMBAT_RESULT_MEDICAL);
return false;
}
obj_id master = getMaster(pet);
if(user != master)
{
sendMedicalSpam(user, SID_ITEM_NOT_YOUR_PET, COMBAT_RESULT_MEDICAL);
return false;
}
if(!isDamaged(pet))
{
sendMedicalSpam(user, SID_ITEM_NO_DAMAGE, COMBAT_RESULT_MEDICAL);
return false;
}
if(!isValidHealTarget(pet))
{
return false;
}
//int food_mod = 1;
if(utils.hasScriptVar(user, VAR_ITEM_TIMER))
{
int reuseTime = utils.getIntScriptVar(user, VAR_ITEM_TIMER);
if(reuseTime > getGameTime())
{
/*
if(buff.hasBuff(user, "drink_ruby_bliel"))
{
buff.removeBuff(user, "drink_ruby_bliel");
food_mod = 2;
}*/
int time_left = reuseTime - getGameTime();
prose_package pp = new prose_package();
pp = prose.setStringId(pp, SID_ITEM_TOO_SOON);
pp = prose.setDI(pp, time_left);
sendMedicalSpam(user, pp, COMBAT_RESULT_MEDICAL);
return false;
}
utils.removeScriptVar(user, VAR_ITEM_TIMER);
}
if(!hasObjVar(item, VAR_ITEM_POWER))
return false;
int power = getIntObjVar(item, VAR_ITEM_POWER);
int delta = healDamage(user, pet, HEALTH, power);
if(delta > 0)
{
decrementCount(item);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, SID_ITEM_PET_HEAL);
pp = prose.setTT(pp, getEncodedName(pet));
pp = prose.setDI(pp, delta);
sendMedicalSpam(user, pp, COMBAT_RESULT_MEDICAL);
//float reuseTime = VAR_ITEM_REUSE_TIME / food_mod;
float reuseTime = VAR_ITEM_REUSE_TIME;
utils.setScriptVar(user, VAR_ITEM_TIMER, (getGameTime() + (reuseTime)));
sendCooldownGroupTimingOnly(user, ##"healItemPet", reuseTime);
doHealingAnimationAndEffect(user, pet);
}
return (delta > 0);
}
boolean canDoBeastHeal(obj_id user, obj_id pet)
{
obj_id beast = beast_lib.getBeastOnPlayer(user);
if(!isIdValid(user) || !exists(user) || isIdNull(user))
return false;
if(!isIdValid(pet) || !exists(pet) || isIdNull(pet))
return false;
if(!isIdValid(beast) || !exists(beast) || isIdNull(beast))
return false;
if(beast != pet)
{
sendSystemMessage(user, new string_id("spam", "not_your_beast") );
return false;
}
obj_id master = getMaster(pet);
if(user != master)
{
sendSystemMessage(user, new string_id("spam", "not_your_beast") );
return false;
}
if(!isDamaged(pet))
{
sendMedicalSpam(user, SID_ITEM_NO_DAMAGE, COMBAT_RESULT_MEDICAL);
return false;
}
if(!isValidHealTarget(pet))
{
return false;
}
return true;
}
boolean doBeastHeal(obj_id user, obj_id pet, int toHeal)
{
if(!canDoBeastHeal(user, pet))
{
return false;
}
int delta = healDamage(user, pet, HEALTH, toHeal);
_addMedicalHate(user, pet, toHeal / 10);
if(delta > 0)
{
prose_package pp = new prose_package();
pp = prose.setStringId(pp, SID_BEAST_MASTER_HEAL);
pp = prose.setTT(pp, getEncodedName(pet));
pp = prose.setDI(pp, delta);
sendMedicalSpam(user, pp, COMBAT_RESULT_MEDICAL);
doHealingAnimationAndEffect(user, pet);
}
return (delta > 0);
}
boolean performRevivePlayer(attacker_data attackerData, defender_data[] defenderData, combat_data actionData, boolean weak)
{
obj_id medic = attackerData.id;
obj_id[] targets = new obj_id[defenderData.length];
for (int i = 0; i < targets.length; i++)
targets[i] = defenderData[i].id;
return _performRevivePlayer(medic, targets, null, actionData, weak);
}
boolean _performRevivePlayer(obj_id medic, obj_id[] targets, obj_id enhancer, combat_data action_data, boolean weak)
{
boolean hasRevivedPlayer = false;
for(int i = 0; i < targets.length; i++)
{
if(!isPlayer(targets[i]))
{
continue;
}
if(!hasObjVar(targets[i], pclib.VAR_BEEN_COUPDEGRACED))
{
continue;
}
if(!utils.hasScriptVar(targets[i], "pvp_death") && action_data.actionName.equals("me_rv_pvp_area"))
{
continue;
}
int stamp = getIntObjVar(targets[i], pclib.VAR_DEATHBLOW_STAMP);
if(getGameTime() > (stamp + REVIVE_TIMER))
{
prose_package pp = new prose_package();
pp = prose.setStringId(pp, SID_PERFORM_REVIVE_TOO_LONG);
pp = prose.setTT(pp, medic);
pp = prose.setTO(pp, targets[i]);
sendMedicalSpam(medic, targets[i], pp, true, true, false, COMBAT_RESULT_MEDICAL);
continue;
}
if(!pvpCanHelp(medic, targets[i]) )
{
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("spam", "revive_no_help_pvp") );
pp = prose.setTO(pp, targets[i]);
sendSystemMessageProse(medic, pp);
continue;
}
dictionary params = new dictionary();
params.put("medic", medic);
if(weak)
params.put("weak", 1);
else
params.put("weak", 0);
pvpHelpPerformed(medic, targets[i]);
hasRevivedPlayer = true;
messageTo(targets[i], "showReviveSUI", params, 0, false);
prose_package reviveAttemptPP = new prose_package();
reviveAttemptPP = prose.setStringId(reviveAttemptPP, new string_id("spam", "revive_attempt") );
reviveAttemptPP = prose.setTO(reviveAttemptPP, targets[i]);
sendSystemMessageProse(medic, reviveAttemptPP);
}
return hasRevivedPlayer;
}
void _addMedicalHate(obj_id medic, obj_id target, int hate)
{
_addMedicalHate(medic, target, hate, 1.0f);
}
void _addMedicalHate(obj_id medic, obj_id target, int hate, float hateMod)
{
obj_id[] hateList = getHateList(target);
if(hateList == null || hateList.length == 0)
return;
if(hateMod < 0.0f)
hateMod = 0.0f;
float hateValue = (float)hate;
hateValue *= hateMod;
for(int i = 0; i < hateList.length; i++)
{
if(!isIdValid(hateList[i]))
continue;
if(medic == hateList[i])
continue;
addHate(hateList[i], medic, hateValue);
addHate(medic, hateList[i], 0.0f);
}
}
float _getEnhancerModifier(obj_id enhancer, float cap)
{
if(!isIdValid(enhancer))
{
return 0.0f;
}
if(cap <= 0.0f)
cap = 1.0f;
float enhancement = 0.0f;
if(hasObjVar(enhancer, VAR_ENHANCER_EFFICIENCY))
enhancement = getFloatObjVar(enhancer, VAR_ENHANCER_EFFICIENCY);
else
{
return 0.0f;
}
float mod = ((enhancement / 1000.0f) * cap);
return mod;
}
float _getSkillModModifier(obj_id medic, string skill_mod, float coeff)
{
if(coeff <= 0.0f)
coeff = 1.0f;
float skill = (float)getEnhancedSkillStatisticModifier(medic, skill_mod);
if(skill <= 0)
return 0.0f;
float mod = 1.0f - (1.0f * (1.0f / ((skill + (1.0f / coeff)) * coeff)));
return mod;
}
float _getMedicalDroidModifier(obj_id medic)
{
float droidMod = 0.0f;
if(pet_lib.isNearMedicalDroid(medic, VAR_SURGICAL_DROID_RANGE))
{
droidMod = 0.2f;
droidMod *= pet_lib.getMedicalDroidMod(medic, VAR_SURGICAL_DROID_RANGE);
}
return droidMod;
}
float _getShockWoundModifier(obj_id target)
{
/*
float shock_mod = 1.0f;
float shock = (float)getShockWound(target);
if(shock > 333.0f)
shock_mod = (333.0f / shock);
return shock_mod;
*/
return 1.0f;
}
void _healingActionFollowUp(obj_id medic, obj_id target, int delta, int type)
{
int[] dArray = new int[1];
dArray[0] = delta;
if (isPlayer(target))
{
if(type == 1)
grantHealingExperience(dArray, medic, target, HEAL_TYPE_MEDICAL_DAMAGE);
else
grantHealingExperience(dArray, medic, target, HEAL_TYPE_MEDICAL_WOUND);
if(medic != target)
{
addHealingKillCredit(medic, target, dArray);
}
}
}
Vector getCombatStates(obj_id target)
{
Vector vStates = new Vector();
return vStates;
}
boolean isDotted(obj_id target, string dot_type)
{
if(dot_type.equals(dot.DOT_BLEEDING))
return dot.isBleeding(target);
else if(dot_type.equals(dot.DOT_POISON))
return dot.isPoisoned(target);
else if(dot_type.equals(dot.DOT_DISEASE))
return dot.isDiseased(target);
else if(dot_type.equals(dot.DOT_FIRE))
return dot.isOnFire(target);
else if(dot_type.equals(dot.DOT_ACID))
return dot.isAcid(target);
else if(dot_type.equals(dot.DOT_ENERGY))
return dot.isEnergy(target);
return false;
}
void startHealOverTime(obj_id target, float duration, float tick, int healPerTick)
{
startHealOverTime(obj_id.NULL_ID, target, "", duration,tick, healPerTick, false);
}
void startHealOverTime(obj_id medic, obj_id target, string actionName, float duration, float tick, int healPerTick, boolean combatFollowUp)
{
if(!isIdValid(target))
return;
if(tick < 1.0f)
tick = 1.0f;
int hot_id = rand(-99999, 99999);
utils.setScriptVar(target, VAR_PLAYER_HOT_ID, hot_id);
int delta = healDamage(medic, target, HEALTH, healPerTick);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("healing", "heal_fly"));
pp = prose.setDI(pp, delta);
pp = prose.setTO(pp, ATTRIBUTES[HEALTH]);
showFlyTextPrivateProseWithFlags(target, target, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
if(medic != target)
showFlyTextPrivateProseWithFlags(target, medic, pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
if (actionName != "")
{
string ascii_id = "perform_" + actionName + "_success";
pp = prose.setStringId(pp, new string_id("healing", ascii_id));
pp = prose.setTT(pp, medic);
pp = prose.setTO(pp, target);
sendMedicalSpam(medic, target, pp, true, true, true, COMBAT_RESULT_MEDICAL);
}
pp = prose.setStringId(pp, SID_PERFORM_HEAL_DAMAGE_SUCCESS);
pp = prose.setTT(pp, medic);
pp = prose.setTO(pp, target);
pp = prose.setDI(pp, delta);
healing.sendMedicalSpam(medic, target, pp, true, true, true, COMBAT_RESULT_MEDICAL);
dictionary d = new dictionary();
d.put("duration", duration);
d.put("tick", tick);
d.put("heal", healPerTick);
d.put("id", hot_id);
d.put("medic", medic);
if(combatFollowUp)
d.put("combat", 1);
else
d.put("combat", 0);
messageTo(target, MSG_HEAL_OVER_TIME, d, tick, false);
//float numTicks = (float)Math.ceil(duration / tick);
//float realDuration = tick * numTicks;
//Use the special icon for trandoshan regeneration species trait.
if(actionName.equals("trandoshan_ability_1") )
buff.applyBuff(target, "trandoshan_ability_1");
else
buff.applyBuff(target, "healOverTime");
}
boolean isAwake(obj_id target)
{
if(isIncapacitated(target))
return false;
if(isDead(target))
return false;
return true;
}
boolean validateTarget(obj_id target, int targetCheck)
{
const int NONE = -1;
const int STANDARD = 0;
const int MOB = 1;
const int CREATURE = 2;
const int NPC = 3;
const int DROID = 4;
const int PVP = 5;
const int JEDI = 6;
const int DEAD = 7;
if(targetCheck != DEAD)
{
if(isDead(target))
return false;
}
switch (targetCheck)
{
case MOB:
return isMob(target) && !vehicle.isVehicle(target);
case CREATURE:
return ai_lib.isMonster(target);
case NPC:
return ai_lib.isNpc(target);
case DROID:
return ai_lib.isDroid(target);
case PVP:
return pvpCanAttack(getSelf(), target);
case JEDI:
if (isPlayer(target))
return isJedi(target);
else
return jedi.isLightsaber(getCurrentWeapon(target));
case DEAD:
return isDead(target);
}
return true;
}
boolean fullHeal(obj_id player)
{
if(!isIdValid(player) || (!isPlayer(player)))
return false;
healShockWound(player, getShockWound(player));
attribute[] maxAttribs = getUnmodifiedMaxAttribs(player);
addAttribModifier(player, maxAttribs[HEALTH].getType(), maxAttribs[HEALTH].getValue(), 0, 0, MOD_POOL);
return true;
}
boolean fullHealEveryone(obj_id creature)
{
if(!isIdValid(creature))
return false;
healShockWound(creature, getShockWound(creature));
attribute[] maxAttribs = getUnmodifiedMaxAttribs(creature);
addAttribModifier(creature, maxAttribs[HEALTH].getType(), maxAttribs[HEALTH].getValue(), 0, 0, MOD_POOL);
return true;
}
boolean healDamage(obj_id player, int amt)
{
return healDamage(player, HEALTH, amt);
}
boolean healDamage(obj_id player, int attrib, int amt)
{
if(!isIdValid(player))
return false;
return addAttribModifier(player, attrib, amt, 0, 0, MOD_POOL);
}
int healDamage(obj_id source, obj_id target, int attrib, int amount)
{
if(!isIdValid(source) || !isIdValid(target) || amount <= 0)
{
return 0;
}
int hBefore = getAttrib(target, attrib);
addAttribModifier(target, attrib, amount, 0, 0, MOD_POOL);
int delta = getAttrib(target, attrib) - hBefore;
if(delta > 0)
{
pvp.bfCreditForHealing(source, delta);
}
return delta;
}
boolean healClone(obj_id player, boolean woundPlayer)
{
if(!isIdValid(player) || (!isPlayer(player)))
return false;
location loc = getLocation(player);
boolean adventurePlanet = false;
int sceneCRC = getStringCrc(loc.area);
switch ( sceneCRC )
{
case ##"tatooine":
case ##"space_tatooine":
case ##"corellia":
case ##"space_corellia":
case ##"naboo":
case ##"space_naboo":
case ##"rori":
case ##"talus":
case ##"dantooine" :
case ##"space_dantooine" :
case ##"dathomir" :
case ##"space_dathomir" :
case ##"yavin4" :
case ##"space_yavin4" :
case ##"lok" :
case ##"space_lok" :
case ##"endor" :
case ##"space_endor" :
case ##"space_heavy1" :
case ##"space_light1" :
adventurePlanet = false;
break;
default:
adventurePlanet = true;
break;
}
float woundReduction = 0f;
//don't consume the player's buff if they won't be wounded:
if ( woundPlayer && !adventurePlanet )
{
if ( utils.hasScriptVar( player, "buff.dessert_gorrnar.value" ) )
{
// Possible food buff mitigation.
float eff = utils.getFloatScriptVar(player, "buff.dessert_gorrnar.value");
buff.removeBuff(player, "dessert_gorrnar");
woundReduction = 1f - (eff / 100f);
}
}
float fltThreshold = .70f;
attribute[] maxAttribs = getUnmodifiedMaxAttribs(player);
int attribValue = maxAttribs[HEALTH].getValue();
float fltTest = (float)attribValue;
fltTest *= fltThreshold;
int intMaxWounds = (int)fltTest;
if (intMaxWounds > 0)
{
setAttrib(player, HEALTH, attribValue);
}
if ( woundPlayer )
{
if ( getConfigSetting("GameServer", "enableCybernetics")!=null )
cybernetic.applyDeathCybernetic( player );
//addShockWound(player, 100);
}
return true;
}
boolean healClone(obj_id player)
{
return healClone(player, true);
}
void sendMedicalSpam(obj_id medic, string_id message, int spam_type)
{
sendCombatSpamMessage(medic, message, spam_type);
}
void sendMedicalSpam(obj_id medic, obj_id target, string_id message, boolean to_attacker, boolean to_defender, boolean to_others, int spam_type)
{
if(medic == target)
sendCombatSpamMessage(medic, target, message, to_attacker, false, to_others, spam_type);
else
sendCombatSpamMessage(medic, target, message, to_attacker, to_defender, to_others, spam_type);
}
void sendMedicalSpam(obj_id medic, prose_package pp, int spam_type)
{
sendCombatSpamMessageProse(medic, pp, spam_type);
}
void sendMedicalSpam(obj_id medic, obj_id target, prose_package pp, boolean to_attacker, boolean to_defender, boolean to_others, int spam_type)
{
if(medic == target)
sendCombatSpamMessageProse(medic, target, pp, to_attacker, false, to_others, spam_type);
else
sendCombatSpamMessageProse(medic, target, pp, to_attacker, to_defender, to_others, spam_type);
}
string[] assembleHealingMessage(int attrib, int delta, obj_id doctor, obj_id target, int heal_type)
{
int[] attribsArray = new int[1];
int[] deltaArray = new int[1];
attribsArray[0] = attrib;
deltaArray[0] = delta;
return assembleHealingMessage(attribsArray, deltaArray, doctor, target, null, heal_type);
}
string[] assembleHealingMessage(int[] attribsArray, int[] deltaArray, obj_id doctor, obj_id target, obj_id medicine)
{
return assembleHealingMessage(attribsArray, deltaArray, doctor, target, medicine, 1);
}
string[] assembleHealingMessage(int[] attribsArray, int[] deltaArray, obj_id doctor, obj_id target, obj_id medicine, int heal_type)
{
resizeable int[] attribs = attribsArray;
resizeable int[] delta = deltaArray;
if(attribs.length != delta.length)
return null;
// Strip out all of the zero deltas. We don't want to message those.
for(int i = 0; i < delta.length; i++)
{
if(delta[i] < 1)
{
attribs = utils.removeElementAt(attribs, i);
delta = utils.removeElementAt(delta, i);
i--; // Set i back one since the arrays have been shortened
}
}
if(attribs.length < 1)
return null;
if(target == doctor)
target = null;
int responseType = 0;
int attribDecWise;
// Determine if we are healing damage or wounds.
if(isIdValid(medicine))
{
if(!isHealDamageMedicine(medicine))
heal_type = 2;
}
if(heal_type == 1) // Healing damage
{
if(attribs.length == 1) // Healing damage to one attribute
{
if(attribs[0] == HEALTH)
{
if(target == null)
responseType = 1; // Healing health damage to self
else
responseType = 2; // Healing health damage to other
}
else if(attribs[0] == ACTION)
{
if(target == null)
responseType = 3; // Healing action damage to self
else
responseType = 4; // Healing action damage to other
}
else if(attribs[0] == MIND)
{
if(target == null)
responseType = 5; // Healing mind damage to self
else
responseType = 6; // Healing mind damage to other
}
else
return null;
}
else if(attribs.length == 2) // Healing damage to two attributes
{
attribDecWise = 0;
attribDecWise = (attribs[0] + attribs[1]);
if(attribDecWise == HEALTH+ACTION)
{
if(target == null)
responseType = 7; // Healing health, and action damage to self
else
responseType = 8; // Healing health, and action damage to other
}
else if(attribDecWise == HEALTH+MIND)
{
if(target == null)
responseType = 9; // Healing health, and mind damage to self
else
responseType = 10; // Healing health, and mind damage to other
}
else if(attribDecWise == HEALTH+ACTION+MIND)
{
if(target == null)
responseType = 11; // Healing action, and mind damage to self
else
responseType = 12; // Healing action, and mind damage to other
}
else
return null;
}
else if(attribs.length == 3) // Healing damage to all three attributes
{
attribDecWise = 0;
attribDecWise = (attribs[0] + attribs[1] + attribs[2]);
if(attribDecWise == HEALTH+ACTION+MIND)
{
if(target == null)
responseType = 13; // Healing health, action, and mind damage to self
else
responseType = 14; // Healing health, action, and mind damage to other
}
else
return null;
}
}
else if(heal_type == 2) // Healing wounds
{
if(attribs.length == 1)
{
if(attribs[0] == HEALTH)
{
if(target == null)
responseType = 15; // Healing health wound damage to self
else
responseType = 16; // Healing health wound damage to other
}
else if(attribs[0] == CONSTITUTION)
{
if(target == null)
responseType = 19; // Healing constitution wound damage to self
else
responseType = 20; // Healing constitution wound damage to other
}
else if(attribs[0] == ACTION)
{
if(target == null)
responseType = 21; // Healing action wound damage to self
else
responseType = 22; // Healing action wound damage to other
}
else if(attribs[0] == STAMINA)
{
if(target == null)
responseType = 25; // Healing stamina wound damage to self
else
responseType = 26; // Healing stamina wound damage to other
}
else if(attribs[0] == MIND)
{
if(target == null)
responseType = 27; // Healing mind wound damage to self
else
responseType = 28; // Healing mind wound damage to other
}
else if(attribs[0] == WILLPOWER)
{
if(target == null)
responseType = 31; // Healing willpower wound damage to self
else
responseType = 32; // Healing willpower wound damage to other
}
}
}
int damage1 = 0;
int damage2 = 0;
int damage3 = 0;
string_id response1;
string_id response2;
string_id response3;
string_id otherResponse1;
string_id otherResponse2;
string_id otherResponse3;
prose_package pp1 = null;
prose_package pp2 = null;
prose_package pp3 = null;
prose_package otherpp1 = null;
prose_package otherpp2 = null;
prose_package otherpp3 = null;
string oob;
string otherOob;
string[] message = {null, null};
switch(responseType)
{
case 1:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 9, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 2:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 12, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 15, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 3:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == ACTION)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 10, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 4:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == ACTION)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 13, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 16, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 5:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == MIND)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 11, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 6:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == MIND)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 14, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 17, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 7:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
else if(attribs[i] == ACTION)
damage2 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 0, 1));
pp1 = prose.getPackage(response1, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 3, 1));
pp2 = prose.getPackage(response2, damage1);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
message[0] = oob;
message[1] = null;
break;
}
case 8:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
else if(attribs[i] == ACTION)
damage2 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 5, 1));
pp1 = prose.getPackage(response1, target, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 3, 1));
pp2 = prose.getPackage(response2, damage2);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 7, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
otherResponse2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 3, 1));
otherpp2 = prose.getPackage(otherResponse2, damage2);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
otherOob = packOutOfBandProsePackage(null, otherpp1);
otherOob = packOutOfBandProsePackage(otherOob, otherpp2);
message[0] = oob;
message[1] = otherOob;
break;
}
case 9:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
else if(attribs[i] == MIND)
damage2 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 0, 1));
pp1 = prose.getPackage(response1, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
pp2 = prose.getPackage(response2, damage1);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
message[0] = oob;
message[1] = null;
break;
}
case 10:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
else if(attribs[i] == MIND)
damage2 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 4, 1));
pp1 = prose.getPackage(response1, target, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
pp2 = prose.getPackage(response2, damage2);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 7, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
otherResponse2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
otherpp2 = prose.getPackage(otherResponse2, damage2);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
otherOob = packOutOfBandProsePackage(null, otherpp1);
otherOob = packOutOfBandProsePackage(otherOob, otherpp2);
message[0] = oob;
message[1] = otherOob;
break;
}
case 11:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == ACTION)
damage1 = delta[i];
else if(attribs[i] == MIND)
damage2 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 4, 1));
pp1 = prose.getPackage(response1, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
pp2 = prose.getPackage(response2, damage1);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
message[0] = oob;
message[1] = null;
break;
}
case 12:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == ACTION)
damage1 = delta[i];
else if(attribs[i] == MIND)
damage2 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 6, 1));
pp1 = prose.getPackage(response1, target, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
pp2 = prose.getPackage(response2, damage2);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 8, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
otherResponse2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
otherpp2 = prose.getPackage(otherResponse2, damage2);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
otherOob = packOutOfBandProsePackage(null, otherpp1);
otherOob = packOutOfBandProsePackage(otherOob, otherpp2);
message[0] = oob;
message[1] = otherOob;
break;
}
case 13:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
else if(attribs[i] == ACTION)
damage2 = delta[i];
else if(attribs[i] == MIND)
damage3 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 0, 1));
pp1 = prose.getPackage(response1, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 1, 1));
pp2 = prose.getPackage(response2, damage2);
response3 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
pp3 = prose.getPackage(response3, damage3);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
oob = packOutOfBandProsePackage(oob, pp3);
message[1] = oob;
message[2] = null;
break;
}
case 14:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
else if(attribs[i] == ACTION)
damage2 = delta[i];
else if(attribs[i] == MIND)
damage3 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 5, 1));
pp1 = prose.getPackage(response1, target, damage1);
response2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 1, 1));
pp2 = prose.getPackage(response2, damage2);
response3 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
pp3 = prose.getPackage(response3, damage3);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 7, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
otherResponse2 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 1, 1));
otherpp2 = prose.getPackage(otherResponse2, damage2);
otherResponse3 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 2, 1));
otherpp3 = prose.getPackage(otherResponse3, damage3);
oob = packOutOfBandProsePackage(null, pp1);
oob = packOutOfBandProsePackage(oob, pp2);
oob = packOutOfBandProsePackage(oob, pp3);
otherOob = packOutOfBandProsePackage(null, otherpp1);
otherOob = packOutOfBandProsePackage(otherOob, otherpp2);
otherOob = packOutOfBandProsePackage(otherOob, otherpp3);
message[0] = oob;
message[1] = otherOob;
break;
}
case 15:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 48, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 16:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == HEALTH)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 51, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 54, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 19:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == CONSTITUTION)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 19, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 20:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == CONSTITUTION)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 31, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 40, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 21:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == ACTION)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 49, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 22:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == ACTION)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 52, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 55, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 25:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == STAMINA)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 21, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 26:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == STAMINA)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 33, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 42, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 27:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == MIND)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 49, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 28:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == MIND)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 53, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 56, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
case 31:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == WILLPOWER)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 23, 1));
pp1 = prose.getPackage(response1, damage1);
oob = packOutOfBandProsePackage(null, pp1);
message[0] = oob;
message[1] = null;
break;
}
case 32:
{
for(int i = 0; i < attribs.length; i++)
{
if(attribs[i] == WILLPOWER)
damage1 = delta[i];
}
response1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 35, 1));
pp1 = prose.getPackage(response1, target, damage1);
otherResponse1 = new string_id(PP_FILE_LOC, utils.dataTableGetString(RESPONSE_TEXT, 44, 1));
otherpp1 = prose.getPackage(otherResponse1, null, null, doctor, damage1);
oob = packOutOfBandProsePackage(null, pp1);
otherOob = packOutOfBandProsePackage(null, otherpp1);
message[0] = oob;
message[1] = otherOob;
break;
}
}
return message;
}
boolean grantHealingExperience(int[] healed_damage, obj_id player, string heal_type)
{
return grantHealingExperience(healed_damage, player, null, heal_type);
}
boolean grantHealingExperience(int[] healed_damage, obj_id player, obj_id target, string heal_type)
{
if(healed_damage == null || !isIdValid(player) || heal_type == null)
return false;
int experience = 0;
int total_healed = 0;
string exp_type;
boolean directGrant = false;
for(int i = 0; i < healed_damage.length; i++)
total_healed = total_healed + healed_damage[i];
if (heal_type.equals(HEAL_TYPE_MEDICAL_DAMAGE))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_WOUND))
{
experience = (int)(total_healed * 5f);
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_BUFF))
{
experience = total_healed * 2;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_STATE))
{
experience = total_healed * 50;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_FIRSTAID))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_POISON))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_FIRE))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_DISEASE))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_POISON))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_DISEASE))
{
experience = total_healed;
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_QUICK_HEAL))
{
return true;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_HEAL_MIND))
{
return true;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_TEND_WOUND))
{
experience = (int)(total_healed * 2.5f);
exp_type = xp.MEDICAL;
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_TEND_DAMAGE))
{
return true;
}
/*
// Entertainer XP should all be handled in the entertainer scripts now
else if(heal_type.equals(HEAL_TYPE_DANCE_WOUND))
{
experience = total_healed / 2;
exp_type = xp.ENTERTAINER;
directGrant = true;
}
else if(heal_type.equals(HEAL_TYPE_DANCE_SHOCK))
{
experience = total_healed * 2;
exp_type = xp.ENTERTAINER;
directGrant = true;
}
else if(heal_type.equals(HEAL_TYPE_DANCE_MIND_BUFF))
{
experience = total_healed;
exp_type = xp.ENTERTAINER;
directGrant = true;
}
else if(heal_type.equals(HEAL_TYPE_MUSIC_WOUND))
{
experience = total_healed / 2;
exp_type = xp.ENTERTAINER;
directGrant = true;
}
else if(heal_type.equals(HEAL_TYPE_MUSIC_SHOCK))
{
experience = total_healed * 2;
exp_type = xp.ENTERTAINER;
directGrant = true;
}
else if(heal_type.equals(HEAL_TYPE_MUSIC_MIND_BUFF))
{
experience = total_healed;
exp_type = xp.ENTERTAINER;
directGrant = true;
}
*/
else if(heal_type.equals(HEAL_TYPE_MEDICAL_REVIVE))
{
experience = 500;
exp_type = xp.MEDICAL;
directGrant = true;
}
else
return false;
if(experience < 1)
return false;
if (directGrant)
xp.grantCombatStyleXp(player, exp_type, experience);
else
assignHealingCombatCredit(player, target, exp_type, experience);
return true;
}
boolean grantHealingExperience(int healed_damage, obj_id player, string heal_type)
{
return grantHealingExperience(healed_damage, player, null, heal_type);
}
boolean grantHealingExperience(int healed_damage, obj_id player, obj_id target, string heal_type)
{
int[] damage_array = {healed_damage};
return grantHealingExperience(damage_array, player, target, heal_type);
}
boolean assignHealingCombatCredit(obj_id player, obj_id target, string xp_type, int amount)
{
if (!isIdValid(target) || !isIdValid(player))
return false;
obj_id[] hateList = getHateList(target);
if (hateList == null || hateList.length == 0)
return false;
for (int i= 0; i < hateList.length; i++)
{
xp.updateCombatXpList(hateList[i], player, xp_type, amount);
}
return true;
}
boolean isDamaged(obj_id player)
{
return isDamaged(player, HEALTH);
}
boolean isDamaged(obj_id player, int attrib)
{
if(!isIdValid(player))
return false;
if(getAttrib(player, attrib) != getWoundedMaxAttrib(player, attrib))
return true;
return false;
}
boolean isWounded(obj_id player, int wound_type)
{
if(!isIdValid(player))
return false;
if(getMaxAttrib(player, HEALTH) == getWoundedMaxAttrib(player, HEALTH))
return false;
else
return true;
}
/***********************************************************************
* @brief Performs the dotremoval process for the specified target.
* Handles messaging, experience, etc.
*
* @param obj_id medic
* @param obj_id target
* @param string heal_type
* @param obj_id med_obj
*
* @return boolean
***********************************************************************/
boolean performDotRemoval(obj_id medic, obj_id target, string heal_type, obj_id med_obj)
{
if(!isIdValid(medic))
return false;
if(!isIdValid(target))
return false;
if(heal_type == null)
return false;
if(isIdValid(med_obj))
{
string[] skillReq = getStringArrayObjVar(med_obj, consumable.VAR_SKILL_MOD_REQUIRED);
int[] skillMin = getIntArrayObjVar(med_obj, consumable.VAR_SKILL_MOD_MIN);
for(int i = 0; i < skillReq.length; i++)
{
int skillMod = getSkillStatMod(medic, skillReq[i]);
if(skillMod < skillMin[i])
{
string[] reqs = new string[skillReq.length];
for(int n = 0; n < skillReq.length; n++)
reqs[n] = skillReq[n] + "[" + getSkillStatMod(medic, skillReq[n]) + "/" + skillMin[n] + "]";
sui.listbox(medic, medic, consumable.MSG_INSUFFICIENT_SKILL, reqs);
sendMedicalSpam(medic, consumable.SID_INSUFFICIENT_SKILL, COMBAT_RESULT_MEDICAL);
return false;
}
}
}
if(!canPayHealingCost(medic, heal_type, 1.0f))
{
sendMedicalSpam(medic, SID_MIND_TOO_DRAINED, COMBAT_RESULT_MEDICAL);
return false;
}
if(medic != target)
{
if(getDistance(medic, target) > consumable.MAX_AFFECT_DISTANCE)
{
sendMedicalSpam(medic, consumable.SID_TARGET_OUT_OF_RANGE, COMBAT_RESULT_OUT_OF_RANGE);
return false;
}
}
int area = 0;
if(isIdValid(med_obj))
area = getHealingArea(med_obj);
obj_id[] valid_targets;
if(area > 0)
{
valid_targets = getHealableTargetsInArea(medic, getLocation(target), area);
if(valid_targets == null)
return false;
}
else
{
valid_targets = new obj_id[1];
valid_targets[0] = target;
}
applyHealingCost(medic, heal_type, 1.0f);
if (isIdValid(med_obj) && !consumable.decrementCharges(med_obj,medic))
return false;
boolean cure_success = false;
float removal_skill;
string dot_type;
for(int i = 0; i < valid_targets.length; i++)
{
if(heal_type.equals(HEAL_TYPE_MEDICAL_FIRSTAID))
{
removal_skill = getEnhancedSkillStatisticModifier(medic, "healing_injury_treatment") * 3.0f;
dot_type = dot.DOT_BLEEDING;
if(dot.isBleeding(valid_targets[i]))
{
if(medic != valid_targets[i])
{
prose_package ppApplyFirstAid = prose.getPackage(SID_YOU_APPLY_FIRST_AID);
prose.setTT(ppApplyFirstAid, valid_targets[i]);
sendMedicalSpam(medic, ppApplyFirstAid, COMBAT_RESULT_MEDICAL);
prose_package ppAppliesFirstAid = prose.getPackage(SID_APPLIES_FIRST_AID);
prose.setTT(ppAppliesFirstAid, medic);
sendMedicalSpam(medic, ppAppliesFirstAid, COMBAT_RESULT_MEDICAL);
}
else
sendMedicalSpam(medic, SID_APPLY_FIRST_AID_SELF, COMBAT_RESULT_MEDICAL);
}
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_POISON))
{
if(!isIdValid(med_obj))
return false;
int cure_power = getDotPower(med_obj);
if(isAreaMedicine(med_obj))
removal_skill = cure_power;
else
removal_skill = cure_power * (1.0f + getEnhancedSkillStatisticModifier(medic, "healing_wound_treatment") / 100.0f);
dot_type = dot.DOT_POISON;
if(dot.isPoisoned(valid_targets[i]))
{
if(medic != valid_targets[i])
{
prose_package ppApplyPoisonAntidote = prose.getPackage(SID_APPLY_POISON_ANTIDOTE);
prose.setTT(ppApplyPoisonAntidote, valid_targets[i]);
sendMedicalSpam(medic, ppApplyPoisonAntidote, COMBAT_RESULT_MEDICAL);
prose_package ppAppliesPoisonAntidote = prose.getPackage(SID_APPLIES_POISON_ANTIDOTE);
prose.setTT(ppAppliesPoisonAntidote, medic);
sendMedicalSpam(valid_targets[i], ppAppliesPoisonAntidote, COMBAT_RESULT_MEDICAL);
}
else
sendMedicalSpam(medic, SID_APPLY_POISON_ANTIDOTE_SELF, COMBAT_RESULT_MEDICAL);
}
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_FIRE))
{
if(!isIdValid(med_obj))
return false;
int cure_power = getDotPower(med_obj);
if(isAreaMedicine(med_obj))
removal_skill = cure_power;
else
removal_skill = cure_power * (1.0f + getEnhancedSkillStatisticModifier(medic, "healing_wound_treatment") / 100.0f);
dot_type = dot.DOT_FIRE;
if(dot.isOnFire(valid_targets[i]))
{
if(medic != valid_targets[i])
{
prose_package ppAttemptSuppress = prose.getPackage(SID_ATTEMPT_SUPPRESS_FLAMES);
prose.setTT(ppAttemptSuppress, valid_targets[i]);
sendMedicalSpam(medic, ppAttemptSuppress, COMBAT_RESULT_MEDICAL);
prose_package ppCoversBlanket = prose.getPackage(SID_COVERS_YOU_BLANKET);
prose.setTT(ppCoversBlanket, medic);
sendMedicalSpam(valid_targets[i], ppCoversBlanket, COMBAT_RESULT_MEDICAL);
}
else
sendMedicalSpam(medic, SID_COVERS_BLANKET_SELF, COMBAT_RESULT_MEDICAL);
}
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_DISEASE))
{
if(!isIdValid(med_obj))
return false;
int cure_power = getDotPower(med_obj);
if(isAreaMedicine(med_obj))
removal_skill = cure_power;
else
removal_skill = cure_power * (1.0f + getEnhancedSkillStatisticModifier(medic, "healing_wound_treatment") / 100.0f);
dot_type = dot.DOT_DISEASE;
if(dot.isDiseased(valid_targets[i]))
{
if(medic != valid_targets[i])
{
prose_package ppApplyDiseaseAntidote = prose.getPackage(SID_APPLY_DISEASE_ANTIDOTE);
prose.setTT(ppApplyDiseaseAntidote, valid_targets[i]);
sendMedicalSpam(medic, ppApplyDiseaseAntidote, COMBAT_RESULT_MEDICAL);
prose_package ppAppliesDiseaseAntidote = prose.getPackage(SID_APPLIES_DISEASE_ANTIDOTE);
prose.setTT(ppAppliesDiseaseAntidote, medic);
sendMedicalSpam(valid_targets[i], ppAppliesDiseaseAntidote, COMBAT_RESULT_MEDICAL);
}
else
sendMedicalSpam(medic, SID_APPLY_DISEASE_ANTIDOTE_SELF, COMBAT_RESULT_MEDICAL);
}
}
else
return false;
int poison_reduced = dot.reduceDotTypeStrength(valid_targets[i], dot_type, (int)removal_skill);
if(poison_reduced != -1)
{
if(isPlayer(valid_targets[i]))
{
if(isIdValid(med_obj) && isAreaMedicine(med_obj))
poison_reduced *= 0.3f;
grantHealingExperience(poison_reduced, medic, valid_targets[i], heal_type);
}
if(medic != valid_targets[i])
{
pvpHelpPerformed(medic, valid_targets[i]);
}
cure_success = true;
}
}
return cure_success;
}
/***********************************************************************
* @brief Performs the application dots for the specified target.
* Handles messaging, experience, etc.
*
* @param obj_id medic
* @param obj_id target
* @param string heal_type
* @param obj_id med_obj
*
* @return boolean false on fail
***********************************************************************/
boolean performDotApplication(obj_id medic, obj_id target, string heal_type, obj_id med_obj)
{
if (!isIdValid(medic))
return false;
if (!isIdValid(target))
return false;
if (!isIdValid(med_obj))
return false;
if (heal_type == null)
return false;
string[] skillReq = getStringArrayObjVar(med_obj, consumable.VAR_SKILL_MOD_REQUIRED);
int[] skillMin = getIntArrayObjVar(med_obj, consumable.VAR_SKILL_MOD_MIN);
for(int i = 0; i < skillReq.length; i++)
{
int skillMod = getSkillStatMod(medic, skillReq[i]);
if(skillMod < skillMin[i])
{
string[] reqs = new string[skillReq.length];
for(int n = 0; n < skillReq.length; n++ )
reqs[n] = skillReq[n] + "[" + getSkillStatMod(medic, skillReq[n]) + "/" + skillMin[n] + "]";
sui.listbox(medic, medic, consumable.MSG_INSUFFICIENT_SKILL, reqs);
sendMedicalSpam(medic, consumable.SID_INSUFFICIENT_SKILL, COMBAT_RESULT_MEDICAL);
return false;
}
}
if(!canPayHealingCost(medic, heal_type, 1.0f))
{
sendMedicalSpam(medic, SID_MIND_TOO_DRAINED, COMBAT_RESULT_MEDICAL);
return false;
}
float healing_range = (float)getHealingRange(med_obj);
float healing_range_mod = (float)getSkillStatMod(medic, "dot_efficiency");
healing_range = healing_range + ((100.0f + healing_range_mod) / 15.0f);
float strength_mod = (float)getSkillStatMod(medic, "dot_efficiency");
if(getDistance(medic, target) > healing_range)
{
sendMedicalSpam(medic, consumable.SID_TARGET_OUT_OF_RANGE, COMBAT_RESULT_OUT_OF_RANGE);
return false;
}
int area = getHealingArea(med_obj);
obj_id[] valid_targets;
if(area > 0)
{
valid_targets = getAttackableTargetsInArea(medic, getLocation(target), area);
if(valid_targets == null)
return false;
}
else
{
valid_targets = new obj_id[1];
valid_targets[0] = target;
}
applyHealingCost(medic, heal_type, 1.0f);
float strength = (float)getDotPower(med_obj) * (1.0f + strength_mod / 100.0f);
int dot_potency = getDotPotency(med_obj);
string dot_id = getDotId(med_obj);
int attribute = getDotAttribute(med_obj);
int duration = getDotDuration(med_obj);
string dot_type;
if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_POISON))
dot_type = dot.DOT_POISON;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_DISEASE))
dot_type = dot_type = dot.DOT_DISEASE;
else
return false;
if(!consumable.decrementCharges(med_obj,medic))
return false;
for(int i = 0; i < valid_targets.length; i++)
{
if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_POISON))
{
prose_package pp_self = prose.getPackage(SID_APPLY_POISON_SELF, valid_targets[i]);
prose_package pp_other = prose.getPackage(SID_APPLY_POISON_OTHER, medic, valid_targets[i]);
sendMedicalSpam(medic, pp_self, COMBAT_RESULT_DEBUFF);
sendMedicalSpam(valid_targets[i], pp_other, COMBAT_RESULT_DEBUFF);
}
else if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_DISEASE))
{
prose_package pp_self = prose.getPackage(SID_APPLY_DISEASE_SELF, valid_targets[i]);
prose_package pp_other = prose.getPackage(SID_APPLY_DISEASE_OTHER, medic, valid_targets[i]);
sendMedicalSpam(medic, pp_self, COMBAT_RESULT_DEBUFF);
sendMedicalSpam(valid_targets[i], pp_other, COMBAT_RESULT_DEBUFF);
}
if(isPlayer(valid_targets[i]))
{
if(factions.pvpDoAllowedAttackCheck(medic, valid_targets[i]))
pvpAttackPerformed(medic, valid_targets[i]);
}
if(dot.applyDotEffect(valid_targets[i], medic, dot_type, dot_id, attribute, dot_potency, (int)strength, duration))
{
if(!isPlayer(valid_targets[i]))
{
grantHealingExperience((int)strength, medic, valid_targets[i], heal_type);
if(!ai_lib.isInCombat(valid_targets[i]))
{
dictionary d = new dictionary();
d.put("attacker", medic);
messageTo(target, "handleDefenderCombatAction", d, 0.0f, true);
}
}
else
{
obj_id[] defenders = new obj_id[1];
defenders[0] = valid_targets[i];
int[] results = new int[1];
results[0] = 1;
callDefenderCombatAction(defenders, results, medic, getCurrentWeapon(medic));
if(factions.pvpDoAllowedAttackCheck(medic, valid_targets[i]))
pvpAttackPerformed(medic, valid_targets[i]);
}
}
else
{
prose_package pp = prose.getPackage(dot.SID_DOT_RESISTED, valid_targets[i]);
sendMedicalSpam(medic, pp, COMBAT_RESULT_GENERIC);
sendMedicalSpam(valid_targets[i], SID_RESIST_DOT_OTHER, COMBAT_RESULT_GENERIC);
}
}
return true;
}
/***********************************************************************
* @brief First aid overload for performDotRemoval
*
* @param obj_id medic
* @param obj_id target
*
* @return boolean
***********************************************************************/
boolean performFirstAid(obj_id medic, obj_id target)
{
return performDotRemoval(medic, target, HEAL_TYPE_MEDICAL_FIRSTAID, null);
}
/***********************************************************************
* @brief Cure poison overload for performDotRemoval
*
* @param obj_id medic
* @param obj_id target
* @param obj_id med_obj
*
* @return boolean
***********************************************************************/
boolean performCurePoison(obj_id medic, obj_id target, obj_id med_obj)
{
return performDotRemoval(medic, target, HEAL_TYPE_MEDICAL_CURE_POISON, med_obj);
}
/***********************************************************************
* @brief Cure fire overload for performDotRemoval
*
* @param obj_id medic
* @param obj_id target
* @param obj_id med_obj
*
* @return boolean
***********************************************************************/
boolean performCureFire(obj_id medic, obj_id target, obj_id med_obj)
{
return performDotRemoval(medic, target, HEAL_TYPE_MEDICAL_CURE_FIRE, med_obj);
}
/***********************************************************************
* @brief Cure disease overload for performDotRemoval
*
* @param obj_id medic
* @param obj_id target
* @param obj_id med_obj
*
* @return boolean
***********************************************************************/
boolean performCureDisease(obj_id medic, obj_id target, obj_id med_obj)
{
return performDotRemoval(medic, target, HEAL_TYPE_MEDICAL_CURE_DISEASE, med_obj);
}
/***********************************************************************
* @brief Apply poison overload for performDotRemoval
*
* @param obj_id medic
* @param obj_id target
* @param obj_id med_obj
*
* @return boolean
***********************************************************************/
boolean performApplyPosion(obj_id medic, obj_id target, obj_id med_obj)
{
return performDotApplication(medic, target, HEAL_TYPE_MEDICAL_APPLY_POISON, med_obj);
}
/***********************************************************************
* @brief Apply disease overload for performDotRemoval
*
* @param obj_id medic
* @param obj_id target
* @param obj_id med_obj
*
* @return boolean
***********************************************************************/
boolean performApplyDisease(obj_id medic, obj_id target, obj_id med_obj)
{
return performDotApplication(medic, target, HEAL_TYPE_MEDICAL_APPLY_DISEASE, med_obj);
}
/***********************************************************************
* @brief Retrieves the first revive pack found in player inv
*
* @param obj_id medic
*
* @return obj_id; null on error
***********************************************************************/
obj_id getRevivePack(obj_id medic)
{
if(!isIdValid(medic))
return null;
obj_id[] contents = utils.getFilteredPlayerContents(medic);
if((contents != null) && (contents.length > 0))
{
for(int i = 0; i < contents.length; i++)
{
obj_id item = contents[i];
if(isIdValid(item))
{
if(isRevivePack(item))
return item;
}
}
}
return null;
}
/***********************************************************************
* @brief determines if an object is a resuscitation kit
*
* @param obj_id pack
*
* @return boolean; false on error
***********************************************************************/
boolean isRevivePack(obj_id pack)
{
return isRevivePack(pack, "");
}
boolean isRevivePack(obj_id pack, string prefix)
{
if(!isIdValid(pack))
return false;
if(getIntObjVar(pack, prefix + consumable.VAR_CONSUMABLE_MED_TYPE) == consumable.MT_REVIVE_PLAYER)
return true;
return false;
}
/***********************************************************************
* @brief attempts to resuscitate target
*
* @param obj_id medic
* @param obj_id target
* @param obj_id pack
*
* @return boolean; false on error
***********************************************************************/
boolean resuscitatePlayer(obj_id medic, obj_id target, obj_id pack)
{
if(!isIdValid(medic) || !isIdValid(target))
return false;
if(!isIdValid(pack))
{
pack = getRevivePack(medic);
if(!isIdValid(pack))
{
sendMedicalSpam(medic, SID_CANNOT_RESUS_WITHOUT_KIT, COMBAT_RESULT_MEDICAL);
return false;
}
}
if(medic == target)
{
sendMedicalSpam(medic, SID_CANNOT_RESUS_WITHOUT_TARGET, COMBAT_RESULT_MEDICAL);
return false;
}
if(!isRevivePack(pack))
{
pack = getRevivePack(medic);
if(!isIdValid(pack))
{
sendMedicalSpam(medic, SID_CANNOT_RESUS_WITHOUT_PACK, COMBAT_RESULT_MEDICAL);
return false;
}
}
if(!hasObjVar(target, pclib.VAR_BEEN_COUPDEGRACED))
return false;
int stamp = getIntObjVar(target, pclib.VAR_DEATHBLOW_STAMP);
if(getGameTime() > (stamp + REVIVE_TIMER))
{
sendMedicalSpam(medic, SID_TARGET_DEAD_TOO_LONG, COMBAT_RESULT_MEDICAL);
return false;
}
if(isJedi(target) && !pclib.hasConsent(medic, target))
{
sendMedicalSpam(medic, SID_MUST_HAVE_JEDI_CONSENT, COMBAT_RESULT_MEDICAL);
return false;
}
if(!group.inSameGroup(medic, target) && !pclib.hasConsent(medic, target))
{
sendMedicalSpam(medic, SID_GROUP_OR_CONSENT_FROM_TARGET, COMBAT_RESULT_MEDICAL);
return false;
}
if(!canPayHealingCost(medic, HEAL_TYPE_MEDICAL_BUFF, 1.0f))
{
sendMedicalSpam(medic, SID_MIND_TOO_DRAINED, COMBAT_RESULT_MEDICAL);
return false;
}
attrib_mod[] am = getAttribModArrayObjVar(pack, consumable.VAR_CONSUMABLE_MODS);
if((am == null) || (am.length == 0))
return false;
if(consumable.consumeItem(medic, target, pack))
{
applyHealingCost(medic, HEAL_TYPE_MEDICAL_REVIVE, 1.0f);
int[] att = new int[WILLPOWER + 1];
for(int i = 0; i < am.length; i++)
{
int attrib = am[i].getAttribute();
float attack = am[i].getAttack();
float decay = am[i].getDecay();
int val = am[i].getValue();
if(attack == AM_HEAL_WOUND)
val *= 2.5;
else if(decay == MOD_POOL)
val /= 4;
if(val > 0)
att[attrib] += val;
}
grantHealingExperience(att, medic, target, HEAL_TYPE_MEDICAL_REVIVE);
pvpHelpPerformed(medic, target);
messageTo(target, "handlePlayerResuscitated", null, 0, true);
return true;
}
return false;
}
boolean resuscitatePlayer(obj_id medic, obj_id target)
{
return resuscitatePlayer(medic, target, null);
}
/***********************************************************************
* @brief determines maximum range for dragging incap players
*
* @param obj_id medic
*
* @return float; -1f on error
***********************************************************************/
float getDragPlayerRange(obj_id medic)
{
if(!isIdValid(medic))
return -1f;
int mod = getSkillStatMod(medic, "healing_ability");
if(mod > 0f)
{
float range = 8f + (22f * ((float)mod/100f));
if(range > 0f)
return range;
}
return -1f;
}
/***********************************************************************
* @brief plays the ranged healing animation
*
* @param obj_id medic
* @param obj_id target
* @param obj_id med_obj
* @param string[] animation element 0 area of effect; element 1 single
* target
*
* @return boolean
***********************************************************************/
boolean playRangedAnimation(obj_id medic, obj_id target, obj_id med_obj, string[] animation)
{
if(!isIdValid(medic))
return false;
if(!isIdValid(target))
return false;
if(!isIdValid(med_obj))
return false;
if(animation == null)
return false;
else if(animation.length != 2)
return false;
if(getPosture(medic) != POSTURE_UPRIGHT)
setPosture(medic, POSTURE_UPRIGHT);
string strPlaybackName = "throw_grenade";
float fltDistance = getDistance(medic, target);
if(fltDistance < 10)
strPlaybackName += "_near";
else if(fltDistance < 20)
strPlaybackName += "_medium";
else
strPlaybackName += "_far";
if(getHealingArea(med_obj) > 0)
strPlaybackName += "_" + animation[0];
else
strPlaybackName += "_" + animation[1];
defender_results[] cbtDefenderResults = new defender_results[1];
cbtDefenderResults[0] = new defender_results(); // data struct newing
attacker_results cbtAttackerResults = new attacker_results();
cbtDefenderResults[0].id = target;
cbtDefenderResults[0].endPosture = getPosture(target);
cbtDefenderResults[0].result = COMBAT_RESULT_HIT;
cbtAttackerResults.id = medic;
cbtAttackerResults.weapon = null;
doCombatResults(strPlaybackName, cbtAttackerResults, cbtDefenderResults);
return true;
}
/***********************************************************************
* @brief plays the heal damage particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playHealDamageEffect(location loc)
{
if(loc == null)
return;
obj_id[] players = getAllPlayers(loc, VAR_EFFECT_DISPLAY_RADIUS);
if(players != null)
{
for(int i = 0; i < players.length; i++)
{
if(isIdValid(players[i]) && exists(players[i]) && !stealth.hasInvisibleBuff(players[i]))
playClientEffectLoc(players[i], "appearance/pt_heal_2.prt" , loc, 0);
}
}
return;
}
/***********************************************************************
* @brief plays the heal wound particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playHealWoundEffect(location loc)
{
if(loc == 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/healing_healwound.cef" , loc, 0);
}
return;
}
/***********************************************************************
* @brief plays the heal state particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playHealStateEffect(location loc)
{
if(loc == 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/healing_healstate.cef" , loc, 0);
}
return;
}
/***********************************************************************
* @brief plays the heal enhance particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playHealEnhanceEffect(location loc)
{
if(loc == 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/healing_healenhance.cef" , loc, 0);
}
return;
}
/***********************************************************************
* @brief plays the apply poison particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playApplyPoisonEffect(location loc)
{
if(loc == 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_apply_poison.cef" , loc, 0);
}
return;
}
/***********************************************************************
* @brief plays the apply area poison particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playApplyAreaPoisonEffect(location loc)
{
if(loc == 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_apply_area_poison.cef" , loc, 0);
}
return;
}
/***********************************************************************
* @brief plays the apply disease particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playApplyDiseaseEffect(location loc)
{
if(loc == 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_apply_disease.cef" , loc, 0);
}
return;
}
/***********************************************************************
* @brief plays the apply area disease particle effect for everyone nearby
*
* @param location loc
*
* @return void
***********************************************************************/
void playApplyAreaDiseaseEffect(location loc)
{
if(loc == 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_apply_area_disease.cef" , loc, 0);
}
return;
}
boolean canDiagnose(obj_id medic, obj_id target)
{
if(!isIdValid(target))
return false;
if(medic == target)
return false;
if(getDistance(medic, target) > consumable.MAX_AFFECT_DISTANCE)
{
sendMedicalSpam(medic, consumable.SID_TARGET_OUT_OF_RANGE, COMBAT_RESULT_OUT_OF_RANGE);
return false;
}
if(!pvpCanHelp(medic, target))
{
sendMedicalSpam(medic, SID_PVP_NO_HELP, COMBAT_RESULT_MEDICAL);
return false;
}
if(!isPlayer(target))
{
if(!pet_lib.isCreaturePet(target) && !pet_lib.isNpcPet(target) || ai_lib.isAndroid(target))
{
sendMedicalSpam(medic, SID_TEND_WOUNDS_INVALID_TARGET, COMBAT_RESULT_MEDICAL);
return false;
}
else //target is in range for diagnose
{
if (!factions.pvpDoAllowedHelpCheck(medic, target)) //if target isn't an enemy
{
LOG("HEALING_MESSAGE_ERROR", medic + " ->It would be unwise to help such a patient.");
sendMedicalSpam(medic, SID_PVP_NO_HELP, COMBAT_RESULT_MEDICAL);
return false;
}
else
{
if (!isPlayer(target)) //if the target isn't a player
{
//if (!pet_lib.isCreaturePet(target) && !pet_lib.isNpcPet(target)) //if target isn't someone's pet
if (!pet_lib.isCreaturePet(target) && !pet_lib.isNpcPet(target) || ai_lib.isAndroid(target)) //if target isn't someone's pet
{
LOG("HEALING_MESSAGE_ERROR", "Target must be a player or a creature pet in order to tend wounds.");
sendMedicalSpam(medic, SID_TEND_WOUNDS_INVALID_TARGET, COMBAT_RESULT_MEDICAL);
return false;
}
else // if the target IS someone's pet
{
return true;
}
}
else // if the target IS a player
{
return true;
}
}
}
}
else
return true;
}
void addHealingKillCredit(obj_id medic, obj_id target, int[] delta)
{
if(!isIdValid(medic))
return;
if(!isIdValid(target))
return;
if(delta == null || delta.length == 0)
return;
if(group.inSameGroup(medic, target) && getState(target, STATE_COMBAT) == 1)
{
int total = 0;
for(int i = 0; i < delta.length; i++)
total += delta[i];
if(total > 0)
{
obj_id combatTarget = getCombatTarget(target);
if(isIdValid(combatTarget))
{
int trackedPermissions = Math.round(total * HEALING_KILL_CREDIT_MULTIPLIER);
//xp.updateCombatXpList(combatTarget, medic, xp.PERMISSIONS_ONLY, trackedPermissions);
if(target != medic)
{
dictionary params = new dictionary();
params.put("healer", medic);
messageTo(combatTarget, "addEnemyHealer", params, 0.0f, false);
}
}
}
}
}
obj_id findDroidWoundMed(obj_id player)
{
if(!isIdValid(player))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(!isIdValid(inventory))
return null;
obj_id[] inv_contents = utils.getContents(inventory, false);
if(inv_contents == null || inv_contents.length == 0)
return null;
for(int i = 0; i < inv_contents.length; i++)
{
if(hasObjVar(inv_contents[i],consumable.VAR_CONSUMABLE_MODS))
{
if(hasObjVar(inv_contents[i], consumable.VAR_CONSUMABLE_DROID_MED))
{
attrib_mod[] mod_array = getAttribModArrayObjVar(inv_contents[i], consumable.VAR_CONSUMABLE_MODS);
if(mod_array != null)
{
for(int j = 0; j < mod_array.length; j++)
{
float attack = mod_array[j].getAttack();
if(attack == AM_HEAL_WOUND)
return inv_contents[i];
}
}
}
}
}
return null;
}
obj_id findDroidDamageMed(obj_id player)
{
if(!isIdValid(player))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(!isIdValid(inventory))
return null;
obj_id[] inv_contents = utils.getContents(inventory, false);
if(inv_contents == null || inv_contents.length == 0)
return null;
for(int i = 0; i < inv_contents.length; i++)
{
if(hasObjVar(inv_contents[i],consumable.VAR_CONSUMABLE_BASE))
{
if(hasObjVar(inv_contents[i], consumable.VAR_CONSUMABLE_DROID_MED))
{
if(hasObjVar(inv_contents[i], "consumable.energy"))
return inv_contents[i];
}
}
}
return null;
}
int[] distributeHAMWoundHealingPoints(obj_id patient, int total) {
int[] toHeal = new int[3];
toHeal[0] = total;
toHeal[1] = 0;
toHeal[2] = 0;
return toHeal;
}
int[] distributeHAMDamageHealingPoints(obj_id patient, int total) {
int[] toHeal = new int[3];
toHeal[0] = total;
toHeal[1] = 0;
toHeal[2] = 0;
return toHeal;
}
boolean isDroidWounded(obj_id patient) {
int hWound = (getMaxAttrib(patient, HEALTH) - getWoundedMaxAttrib(patient, HEALTH));
if(hWound > 0)
return true;
return false;
}
boolean isDroidDamaged(obj_id patient) {
int hDamage = (getWoundedMaxAttrib(patient, HEALTH) - getAttrib(patient, HEALTH));
if(hDamage > 0)
return true;
return false;
}
boolean performDroidRepair(obj_id medic, obj_id target, obj_id med_obj, boolean pay_cost) {
if(!isIdValid(medic))
return false;
if(!isIdValid(target))
return false;
if(!isIdValid(med_obj))
return false;
boolean isDroidPetMed = hasObjVar(med_obj, consumable.VAR_CONSUMABLE_DROID_MED);
boolean isDamageMed = hasObjVar(med_obj, "consumable.energy");
if(!isDroidPetMed)
return false;
string costType = HEAL_TYPE_MEDICAL_WOUND;
if(isDamageMed)
costType = HEAL_TYPE_MEDICAL_DAMAGE;
if(pay_cost)
{
if(!canPayHealingCost(medic, costType, 1.0f))
{
sendMedicalSpam(medic, SID_NOT_ENOUGH_MIND, COMBAT_RESULT_MEDICAL);
return false;
}
}
int health_before = getAttrib(target,HEALTH);
if(consumable.consumeItem(medic, target, med_obj))
{
if(pay_cost)
applyHealingCost(medic, costType, 1.0f);
int health_after = getAttrib(target,HEALTH);
int totalHealed = health_after - health_before;
int[] delta = {totalHealed};
obj_id target_master = getMaster(target);
prose_package pp_self;
prose_package pp_other;
if(isDamageMed)
{
pp_self = prose.getPackage(SID_DROID_REPAIR_DAMAGE_SELF, getEncodedName(target), totalHealed);
pp_other = prose.getPackage(SID_DROID_REPAIR_DAMAGE_OTHER, getFirstName(medic), getEncodedName(target), totalHealed);
}
else
{
pp_self = prose.getPackage(SID_DROID_REPAIR_WOUND_SELF, getEncodedName(target), totalHealed);
pp_other = prose.getPackage(SID_DROID_REPAIR_WOUND_OTHER, getFirstName(medic), getEncodedName(target), totalHealed);
}
sendMedicalSpam(medic, pp_self, COMBAT_RESULT_MEDICAL);
if((target_master != null) && (medic != target_master))
{
if(isIdValid(target_master))
sendMedicalSpam(target_master, pp_other, COMBAT_RESULT_MEDICAL);
pvpHelpPerformed(medic, target);
if(isDamageMed)
addHealingKillCredit(medic, target, delta);
}
return true;
}
return false;
}
obj_id findStimpackDispensorDroid(obj_id player)
{
if(!isIdValid(player))
return null;
obj_id[] creatures = getCreaturesInRange(getLocation(player), VAR_STIMPACK_DROID_RADIUS);
if(creatures != null)
{
for(int i = 0; i < creatures.length; i++)
{
if(pet_lib.isDroidPet(creatures[i]))
{
if(hasObjVar(creatures[i], "module_data.stimpack_capacity"))
{
if(getIntObjVar(creatures[i], "module_data.stimpack_supply") > 0)
{
if(!utils.hasScriptVar(creatures[i], "module_data.stimpack_recharging"))
{
obj_id master = getMaster(creatures[i]);
if(isIdValid(master))
{
if((master == player) || group.inSameGroup(master, player))
return creatures[i];
}
}
}
}
}
}
}
return null;
}
//////////////////////////////////////////////////////////
//
// DEPRECATED FUNCTIONS
//
// These should be deleted as soon as we know no other
// systems are using them
//
//////////////////////////////////////////////////////////
boolean isMedicine(obj_id object)
{
return isMedicine(object, "");
}
boolean isMedicine(obj_id object, string prefix)
{
if(!isIdValid(object))
return false;
if(hasObjVar(object, prefix + consumable.VAR_CONSUMABLE_MEDICINE))
return true;
else
return false;
}
boolean isRangedMedicine(obj_id object)
{
return isRangedMedicine(object, "", false);
}
boolean isRangedMedicine(obj_id object, string prefix, boolean inDocBag)
{
if(!isIdValid(object))
return false;
if(inDocBag)
{
if(hasObjVar(object, prefix + "healing.dot_info"))
{
int[] healingInfo = getIntArrayObjVar(object, prefix + "healing.dot_info");
if(healingInfo[0] > 0)
return true;
}
return false;
}
else
{
if(hasObjVar(object, VAR_HEALING_RANGE))
return true;
else
return false;
}
}
boolean isAreaMedicine(obj_id object)
{
if (!isIdValid(object))
return false;
if (hasObjVar(object, VAR_HEALING_AREA))
return true;
else
return false;
}
boolean isHealDamageMedicine(obj_id medicine)
{
return isHealDamageMedicine(medicine, "");
}
boolean isHealDamageMedicine(obj_id medicine, string prefix)
{
if (!isIdValid(medicine))
return false;
attrib_mod[] mod_array = getAttribModArrayObjVar(medicine, prefix + consumable.VAR_CONSUMABLE_MODS);
if (mod_array == null)
return false;
for (int i = 0; i < mod_array.length; i++)
{
int attribute = mod_array[i].getAttribute();
float decay = mod_array[i].getDecay();
if((attribute != HEALTH) && (attribute != ACTION) && (attribute != MIND))
{} // return false;
if(decay != MOD_POOL)
return false;
}
return true;
}
boolean isHealStateMedicine(obj_id medicine)
{
return isHealStateMedicine(medicine, "");
}
boolean isHealStateMedicine(obj_id medicine, string prefix)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, prefix + VAR_HEALING_STATE))
return true;
else
return false;
}
boolean isBuffMedicine(obj_id medicine)
{
return isBuffMedicine(medicine, "");
}
boolean isBuffMedicine(obj_id medicine, string prefix)
{
if(!isIdValid(medicine))
return false;
if(!isMedicine(medicine, prefix))
return false;
attrib_mod[] mod_array = getAttribModArrayObjVar(medicine, prefix + consumable.VAR_CONSUMABLE_MODS);
if(mod_array == null)
return false;
for(int i = 0; i < mod_array.length; i++)
{
float duration = mod_array[i].getDuration();
if (duration < 1.0f)
return false;
}
return true;
}
boolean isCureDotMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_CURE_DOT))
return true;
else
return false;
}
boolean isApplyDotMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_APPLY_DOT))
return true;
else
return false;
}
boolean isCurePoisonMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_CURE_DOT))
{
string type = getStringObjVar(medicine, VAR_HEALING_CURE_DOT);
if(type.equals(dot.DOT_POISON))
return true;
else
return false;
}
else
return false;
}
boolean isCureFireMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_CURE_DOT))
{
string type = getStringObjVar(medicine, VAR_HEALING_CURE_DOT);
if(type.equals(dot.DOT_FIRE))
return true;
else
return false;
}
else
return false;
}
boolean isCureDiseaseMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_CURE_DOT))
{
string type = getStringObjVar(medicine, VAR_HEALING_CURE_DOT);
if(type.equals(dot.DOT_DISEASE))
return true;
else
return false;
}
else
return false;
}
boolean isApplyPoisonMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_APPLY_DOT))
{
string type = getStringObjVar(medicine, VAR_HEALING_APPLY_DOT);
if(type.equals(dot.DOT_POISON))
return true;
else
return false;
}
else
return false;
}
boolean isApplyDiseaseMedicine(obj_id medicine)
{
if(!isIdValid(medicine))
return false;
if(hasObjVar(medicine, VAR_HEALING_APPLY_DOT))
{
string type = getStringObjVar(medicine, VAR_HEALING_APPLY_DOT);
if(type.equals(dot.DOT_DISEASE))
return true;
else
return false;
}
else
return false;
}
int getHealingRange(obj_id medicine)
{
if(!isIdValid(medicine))
return 0;
if(isRangedMedicine(medicine))
return getIntObjVar(medicine, VAR_HEALING_RANGE);
else
return 0;
}
int getHealingArea(obj_id medicine)
{
if(!isIdValid(medicine))
return 0;
if(hasObjVar(medicine, VAR_HEALING_AREA))
return getIntObjVar(medicine, VAR_HEALING_AREA);
else
return 0;
}
string getHealingState(obj_id medicine)
{
return getHealingState(medicine, "");
}
string getHealingState(obj_id medicine, string prefix)
{
if(!isIdValid(medicine))
return null;
if(isHealStateMedicine(medicine, prefix))
return getStringObjVar(medicine, prefix + VAR_HEALING_STATE);
else
return null;
}
string getCureDot(obj_id medicine)
{
return getCureDot(medicine, "");
}
string getCureDot(obj_id medicine, string prefix)
{
if(!isIdValid(medicine))
return null;
if(hasObjVar(medicine, prefix + VAR_HEALING_CURE_DOT))
return getStringObjVar(medicine, prefix + VAR_HEALING_CURE_DOT);
else
return null;
}
string getApplyDot(obj_id medicine)
{
return getApplyDot(medicine, "");
}
string getApplyDot(obj_id medicine, string prefix)
{
if(!isIdValid(medicine))
return null;
if(hasObjVar(medicine, prefix + VAR_HEALING_APPLY_DOT))
return getStringObjVar(medicine, prefix + VAR_HEALING_APPLY_DOT);
else
return null;
}
int getDotPower(obj_id medicine)
{
if(!isIdValid(medicine))
return -1;
if(hasObjVar(medicine, VAR_HEALING_DOT_POWER))
return getIntObjVar(medicine, VAR_HEALING_DOT_POWER);
else
return -1;
}
int getDotPotency(obj_id medicine)
{
if(!isIdValid(medicine))
return -1;
if(hasObjVar(medicine, VAR_HEALING_DOT_POTENCY))
return getIntObjVar(medicine, VAR_HEALING_DOT_POTENCY);
else
return -1;
}
string getDotId(obj_id medicine)
{
if(!isIdValid(medicine))
return null;
if(hasObjVar(medicine, VAR_HEALING_DOT_ID))
return getStringObjVar(medicine, VAR_HEALING_DOT_ID);
else
return null;
}
int getDotAttribute(obj_id medicine)
{
if(!isIdValid(medicine))
return -1;
if(hasObjVar(medicine, VAR_HEALING_DOT_ATTRIBUTE))
return getIntObjVar(medicine, VAR_HEALING_DOT_ATTRIBUTE);
else
return -1;
}
int getDotDuration(obj_id medicine)
{
if(!isIdValid(medicine))
return -1;
if(hasObjVar(medicine, VAR_HEALING_DOT_DURATION))
return getIntObjVar(medicine, VAR_HEALING_DOT_DURATION);
else
return -1;
}
float getHealingMultiplier(obj_id player, obj_id item, string type)
{
float healing_skill = 0.0f;
boolean medical_type = false;
boolean entertainer_type = false;
float random_factor = rand(50, 150);
if(type.equals(HEAL_TYPE_MEDICAL_DAMAGE) || type.equals(HEAL_TYPE_MEDICAL_QUICK_HEAL) || type.equals(HEAL_TYPE_MEDICAL_TEND_DAMAGE))
{
medical_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_efficiency");
}
else if(type.equals(HEAL_TYPE_MEDICAL_WOUND) || type.equals(HEAL_TYPE_MEDICAL_TEND_WOUND))
{
medical_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_efficiency");
}
else if(type.equals(HEAL_TYPE_MEDICAL_HEAL_MIND))
{
medical_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "dot_efficiency");
}
else if(type.equals(HEAL_TYPE_MEDICAL_BUFF))
{
medical_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_efficiency");
random_factor = 100;
}
else if(type.equals(HEAL_TYPE_DANCE_WOUND))
{
entertainer_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_dance_wound");
}
else if(type.equals(HEAL_TYPE_DANCE_SHOCK))
{
entertainer_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_dance_shock");
}
else if(type.equals(HEAL_TYPE_MUSIC_WOUND))
{
entertainer_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_music_wound");
}
else if(type.equals(HEAL_TYPE_MUSIC_SHOCK))
{
entertainer_type = true;
healing_skill = (float)getEnhancedSkillStatisticModifier(player, "healing_music_shock");
}
float complexity = 0.0f;
if(item != null || item != obj_id.NULL_ID)
complexity = getComplexity(item);
float medicalDroidModifier = 0.0f;
float multiplier = 0.0f;
if(pet_lib.isNearMedicalDroid(player, VAR_SURGICAL_DROID_RANGE))
medicalDroidModifier = pet_lib.getMedicalDroidMod(player, VAR_SURGICAL_DROID_RANGE);
if(medicalDroidModifier > 0.0f)
multiplier = (1 + healing_skill / 100) * (random_factor / 100) * medicalDroidModifier;
else
multiplier = (1 + healing_skill / 100) * (random_factor / 100);
if(entertainer_type)
{
int city_id = city.checkCity(player, false);
if(city_id > 0 && (city.cityHasSpec(city_id, city.SF_SPEC_ENTERTAINER) || city.cityHasSpec(city_id, city.SF_SPEC_MASTER_HEALING)))
multiplier *= 1.1f;
}
if(medical_type)
{
int city_id = city.checkCity(player, false);
if(city_id > 0 && (city.cityHasSpec(city_id, city.SF_SPEC_DOCTOR) || city.cityHasSpec(city_id, city.SF_SPEC_MASTER_HEALING)))
multiplier *= 1.1f;
}
return multiplier;
}
float getHealingMultiplier(obj_id player, obj_id item)
{
if(isHealDamageMedicine(item))
return getHealingMultiplier(player, item, HEAL_TYPE_MEDICAL_DAMAGE);
else if(isBuffMedicine(item))
return getHealingMultiplier(player, item, HEAL_TYPE_MEDICAL_BUFF);
else
return getHealingMultiplier(player, item, HEAL_TYPE_MEDICAL_WOUND);
}
boolean hasEnhancement(obj_id player, int attribute)
{
if(!isIdValid(player))
return true;
string buff_name = "medical_enhance_" + attributeToString(attribute).toLowerCase();
if(hasAttribModifier(player, buff_name) || hasSkillModModifier(player, buff_name))
return true;
else
return false;
}
int getHealEnhanceValue(obj_id player, int attribute)
{
if(!isIdValid(player))
return -1;
string buff_name = "medical_enhance_" + attributeToString(attribute).toLowerCase();
attrib_mod[] all_am = getAttribModifiers(player, attribute);
if (all_am != null && all_am.length > 0)
{
for (int i = 0; i < all_am.length; i++)
{
if (all_am[i].getName().equals(buff_name))
return all_am[i].getValue();
}
}
if (utils.hasScriptVar(player, "healing." + buff_name))
return utils.getIntScriptVar(player, "healing." + buff_name);
return 0;
}
float applyShockWoundModifier(float multiplier, obj_id player)
{
float shock = (float)getShockWound(player);
if(shock < 1)
return multiplier;
else
{
float shock_mult = (1250.0f - shock) / 1000.0f;
if(shock_mult > 1.0f)
shock_mult = 1.0f;
else if(shock_mult < 0.25f)
shock_mult = 0.25f;
multiplier *= shock_mult;
if(multiplier < 0)
multiplier = 0;
return multiplier;
}
}
attrib_mod[] modifyMedicineAttributes(attrib_mod[] am, float multiplier)
{
resizeable attrib_mod[] am_new = new attrib_mod[0];
for(int i = 0; i < am.length; i++)
{
attrib_mod tmp;
int mod_value;
if(am[i].getAttack() == AM_HEAL_WOUND)
{
mod_value = (int)(am[i].getValue() * multiplier);
tmp = utils.createHealWoundAttribMod(am[i].getAttribute(), mod_value);
am_new = utils.addElement(am_new, tmp);
}
else
{
if(am[i].getDecay() == MOD_POOL)
{
mod_value = (int)(am[i].getValue() * multiplier);
tmp = utils.createHealDamageAttribMod(am[i].getAttribute(), mod_value);
am_new = utils.addElement(am_new, tmp);
}
else
{
mod_value = (int)(am[i].getValue() * multiplier);
tmp = new attrib_mod(am[i].getAttribute(), mod_value, am[i].getDuration(), VAR_BUFF_MOD_ATTACK, VAR_BUFF_MOD_DECAY);
am_new = utils.addElement(am_new, tmp);
}
}
}
return am_new;
}
boolean canHealDamage(obj_id player, boolean verbose)
{
if(!isIdValid(player))
return false;
if(!hasObjVar(player, VAR_HEALING_CAN_HEALDAMAGE))
setObjVar(player, VAR_HEALING_CAN_HEALDAMAGE, 0);
int healing_roundtime = getIntObjVar(player, VAR_HEALING_CAN_HEALDAMAGE);
if(healing_roundtime != 0)
{
if(verbose)
{
int time_remaining = (healing_roundtime - getGameTime());
if(time_remaining > 0)
{
int[] conv_time = player_structure.convertSecondsTime(time_remaining);
string time_str = player_structure.assembleTimeRemaining(conv_time);
prose_package ppNoTime = prose.getPackage(SID_CANNOT_DO_THAT_TIME);
prose.setTO(ppNoTime, time_str);
sendMedicalSpam(player, ppNoTime, COMBAT_RESULT_MEDICAL);
}
else
sendMedicalSpam(player, SID_YOU_MUST_WAIT, COMBAT_RESULT_MEDICAL);
}
return false;
}
int injury_skill = getSkillStatMod(player, "healing_injury_treatment");
if(injury_skill == 0)
{
if(verbose)
sendMedicalSpam(player, SID_CANT_HEAL_DAMAGE_OR_STATES, COMBAT_RESULT_MEDICAL);
return false;
}
return true;
}
boolean canHealDamage(obj_id player)
{
return canHealDamage(player, true);
}
boolean canHealWound(obj_id player, boolean verbose)
{
if(!isIdValid(player))
return false;
location loc = getLocation(player);
if(isIdValid(loc.cell))
{
obj_id building = getTopMostContainer(loc.cell);
if(building != null && building != obj_id.NULL_ID)
{
if(!hasObjVar(building, "healing.canhealwound"))
{
if(verbose)
sendMedicalSpam(player, SID_MUST_BE_IN_HOSPITAL_OR_CS, COMBAT_RESULT_MEDICAL);
return false;
}
}
}
else
{
obj_id camp = camping.getCurrentCamp(player);
if(!isIdValid(camp))
{
if(!pet_lib.isNearMedicalDroid(player, VAR_SURGICAL_DROID_RANGE))
{
if(verbose)
sendMedicalSpam(player, SID_MUST_BE_IN_HOSP_OR_CS_OR_DROID, COMBAT_RESULT_MEDICAL);
return false;
}
}
}
if(!hasObjVar(player, VAR_HEALING_CAN_HEALWOUND))
setObjVar(player, VAR_HEALING_CAN_HEALWOUND, 0);
int healing_roundtime = getIntObjVar(player, VAR_HEALING_CAN_HEALWOUND);
if(healing_roundtime != 0)
{
if(verbose)
{
int time_remaining = (healing_roundtime - getGameTime());
if(time_remaining > 0)
{
int[] conv_time = player_structure.convertSecondsTime(time_remaining);
string time_str = player_structure.assembleTimeRemaining(conv_time);
prose_package ppNoTime = prose.getPackage(SID_CANNOT_DO_THAT_TIME);
prose.setTO(ppNoTime, time_str);
sendMedicalSpam(player, ppNoTime, COMBAT_RESULT_MEDICAL);
}
else
sendMedicalSpam(player, SID_MUST_WAIT_TO_HEAL_OR_ENHANCE, COMBAT_RESULT_MEDICAL);
}
return false;
}
int injury_skill = getSkillStatMod(player, "healing_wound_treatment");
if(injury_skill == 0)
{
if(verbose)
sendMedicalSpam(player, SID_NO_HEAL_OR_ENHANCE_ABILITY, COMBAT_RESULT_MEDICAL);
return false;
}
return true;
}
boolean canHealWound(obj_id player)
{
return canHealWound(player, true);
}
boolean canPayHealingCost(obj_id player, string heal_type, float modifier)
{
if(!isIdValid(player) || heal_type == null || heal_type.equals(""))
return false;
if(modifier <= 0)
return false;
int mind = getAttrib(player, MIND);
int cost = 0;
if (heal_type.equals(HEAL_TYPE_MEDICAL_DAMAGE))
cost = VAR_HEALDAMAGE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_WOUND))
cost = VAR_HEALWOUND_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_STATE))
cost = VAR_HEALSTATE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_BUFF))
cost = VAR_HEALENHANCE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_REVIVE))
cost = COST_MIND_REVIVE;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_FIRSTAID))
cost = VAR_FIRSTAID_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_CURE_POISON))
cost = VAR_CURE_POISON_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_CURE_FIRE))
cost = VAR_CURE_FIRE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_CURE_DISEASE))
cost = VAR_CURE_DISEASE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_POISON))
cost = VAR_APPLY_POISON_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_DISEASE))
cost = VAR_APPLY_DISEASE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_QUICK_HEAL))
cost = VAR_QUICK_HEAL_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_TEND_WOUND))
cost = VAR_TEND_WOUND_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_TEND_DAMAGE))
cost = VAR_TEND_DAMAGE_COST;
else if (heal_type.equals(HEAL_TYPE_MEDICAL_HEAL_MIND))
cost = VAR_HEAL_MIND_COST;
else
return false;
cost = (int)(cost * modifier);
if(mind < cost)
return false;
else
return true;
}
float setCanHealDamage(obj_id player, int roundtime)
{
if(!isIdValid(player))
return -1f;
float newroundtime = 0.0f;
if(!hasObjVar(player, VAR_HEALING_CAN_HEALDAMAGE))
setObjVar(player, VAR_HEALING_CAN_HEALDAMAGE, 0);
if(roundtime == 0)
setObjVar(player, VAR_HEALING_CAN_HEALDAMAGE, 0);
else
setObjVar(player, VAR_HEALING_CAN_HEALDAMAGE, getGameTime() + (int)newroundtime);
return newroundtime;
}
boolean setCanHealWound(obj_id player, int roundtime)
{
if(!isIdValid(player))
return false;
if(!hasObjVar(player, VAR_HEALING_CAN_HEALWOUND))
setObjVar(player, VAR_HEALING_CAN_HEALWOUND, 0);
if (roundtime == 0)
setObjVar(player, VAR_HEALING_CAN_HEALWOUND, 0);
else
setObjVar(player, VAR_HEALING_CAN_HEALWOUND, getGameTime() + roundtime);
return true;
}
obj_id findHealDamageMedicine(obj_id player, obj_id target)
{
obj_id med_obj = null;
if (!isIdValid(player))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if (!isIdValid(inventory))
return null;
if (utils.hasScriptVar(player, SCRIPT_VAR_RANGED_MED))
utils.removeScriptVar(player, SCRIPT_VAR_RANGED_MED);
if (utils.hasScriptVar(player, SCRIPT_VAR_DAMAGE_MED))
utils.removeScriptVar(player, SCRIPT_VAR_DAMAGE_MED);
string prefix = "";
obj_id[] inv_contents = utils.getContents(inventory, false);
for (int i = 0; (i < inv_contents.length) && (med_obj==null); i++)
{
prefix = "";
int loop_count = 1;
boolean set_prefix = false;
if(doctor_bag.isDoctorBag( inv_contents[i]))
{
set_prefix = true;
loop_count = doctor_bag.MAX_MEDS;
}
for(int k=0; (k<loop_count) && (med_obj==null); k++)
{
if(set_prefix)
{
prefix = "meds." + k + ".";
if(!hasObjVar(inv_contents[i], "meds." + k))
continue;
}
if(hasObjVar(inv_contents[i],prefix+consumable.VAR_CONSUMABLE_MODS))
{
if(isMedicine(inv_contents[i], prefix))
{
if(isHealDamageMedicine(inv_contents[i], prefix))
{
if((!hasObjVar(inv_contents[i], prefix + consumable.VAR_CONSUMABLE_PET_MED)) && (!hasObjVar(inv_contents[i], prefix + consumable.VAR_CONSUMABLE_DROID_MED)))
{
if(isIdValid(target) && getDistance(player, target) >= consumable.MAX_AFFECT_DISTANCE)
{
if(isRangedMedicine(inv_contents[i],prefix,set_prefix))
med_obj = inv_contents[i];
else
{
utils.setScriptVar(player, SCRIPT_VAR_DAMAGE_MED, inv_contents[i]);
utils.removeScriptVar(player, "healing.prefix");
if(set_prefix)
utils.setScriptVar(player, "healing.prefix", prefix);
}
}
else
{
if(!isRangedMedicine(inv_contents[i], prefix, set_prefix))
med_obj = inv_contents[i];
else
{
utils.setScriptVar(player, SCRIPT_VAR_RANGED_MED, inv_contents[i]);
utils.removeScriptVar(player, "healing.prefix");
if(set_prefix)
utils.setScriptVar(player, "healing.prefix", prefix);
}
}
}
}
}
}
}
}
if(med_obj == null)
{
if(utils.hasScriptVar(player, SCRIPT_VAR_RANGED_MED))
med_obj = utils.getObjIdScriptVar(player, SCRIPT_VAR_RANGED_MED);
else
{
if(utils.hasScriptVar(player, SCRIPT_VAR_DAMAGE_MED))
med_obj = utils.getObjIdScriptVar(player, SCRIPT_VAR_DAMAGE_MED);
}
if(utils.hasScriptVar(player, "healing.prefix"))
prefix = utils.getStringScriptVar(player, "healing.prefix");
}
if(med_obj != null)
{
if(doctor_bag.isDoctorBag(med_obj))
doctor_bag.setSurrogateState(med_obj, prefix);
}
return med_obj;
}
obj_id findHealDamageMedicine(obj_id player)
{
return findHealDamageMedicine(player, null);
}
obj_id findHealWoundMedicine(obj_id player, int wound_type)
{
obj_id med_obj = null;
if(!isIdValid(player))
return null;
if((wound_type < 0) || (wound_type >= NUM_ATTRIBUTES))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(inventory == null)
return null;
string prefix = "";
obj_id[] inv_contents = utils.getContents(inventory, false);
for(int i = 0; (i < inv_contents.length) && (med_obj==null); i++)
{
prefix = "";
int loop_count = 1;
boolean set_prefix = false;
if(doctor_bag.isDoctorBag(inv_contents[i]))
{
set_prefix = true;
loop_count = doctor_bag.MAX_MEDS;
}
for(int k=0; (k<loop_count) && (med_obj==null); k++)
{
if(set_prefix)
{
prefix = "meds." + k + ".";
if(!hasObjVar(inv_contents[i], "meds." + k))
continue;
}
if(hasObjVar(inv_contents[i], prefix + consumable.VAR_CONSUMABLE_MODS))
{
if(isMedicine(inv_contents[i], prefix))
{
if(!isRevivePack(inv_contents[i], prefix))
{
attrib_mod[] mod_array = getAttribModArrayObjVar(inv_contents[i], prefix+consumable.VAR_CONSUMABLE_MODS);
if(mod_array != null)
{
for(int j = 0; j < mod_array.length; j++)
{
int attribute = mod_array[j].getAttribute();
float attack = mod_array[j].getAttack();
if((attribute == wound_type)&&(attack == AM_HEAL_WOUND))
med_obj = inv_contents[i];
}
}
}
}
}
}
}
if(med_obj != null)
{
if(doctor_bag.isDoctorBag(med_obj))
doctor_bag.setSurrogateState(med_obj, prefix);
}
return med_obj;
}
obj_id findHealStateMedicine(obj_id player, int state_type)
{
obj_id med_obj = null;
if(player == null || player == obj_id.NULL_ID)
return null;
if(state_type < 12 || state_type > 15)
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(inventory == null)
return null;
string prefix = "";
obj_id[] inv_contents = utils.getContents(inventory, false);
for(int i = 0; (i < inv_contents.length) && (med_obj==null); i++)
{
prefix = "";
int loop_count = 1;
boolean set_prefix = false;
if(doctor_bag.isDoctorBag(inv_contents[i]))
{
set_prefix = true;
loop_count = doctor_bag.MAX_MEDS;
}
for(int k=0; (k<loop_count) && (med_obj==null); k++)
{
if(set_prefix)
{
prefix = "meds." + k + ".";
if(!hasObjVar(inv_contents[i], "meds."+k))
continue;
}
if(isMedicine(inv_contents[i], prefix))
{
if(isHealStateMedicine(inv_contents[i],prefix))
{
string med_state = getHealingState(inv_contents[i],prefix);
int med_state_type = stringToState(med_state);
if(state_type == med_state_type)
med_obj = inv_contents[i];
}
}
}
}
if(med_obj != null)
{
if(doctor_bag.isDoctorBag(med_obj))
doctor_bag.setSurrogateState(med_obj, prefix);
}
return med_obj;
}
obj_id findBuffMedicine(obj_id player, int buff_type)
{
if(player == null || player == obj_id.NULL_ID)
return null;
obj_id med_obj = null;
if(!isIdValid(player))
return null;
if((buff_type < 0)||(buff_type > 10))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(inventory == null)
return null;
string prefix = "";
obj_id[] inv_contents = utils.getContents(inventory, false);
for(int i = 0; (i < inv_contents.length) && (med_obj==null); i++)
{
prefix = "";
int loop_count = 1;
boolean set_prefix = false;
if(doctor_bag.isDoctorBag(inv_contents[i]))
{
set_prefix = true;
loop_count = doctor_bag.MAX_MEDS;
}
for(int k=0; (k<loop_count) && (med_obj==null); k++)
{
if(set_prefix)
{
prefix = "meds." + k + ".";
if(!hasObjVar(inv_contents[i], "meds." + k))
continue;
}
if(hasObjVar(inv_contents[i],prefix+consumable.VAR_CONSUMABLE_MODS))
{
if(isBuffMedicine(inv_contents[i],prefix))
{
attrib_mod[] mod_array = getAttribModArrayObjVar(inv_contents[i], prefix+consumable.VAR_CONSUMABLE_MODS);
if(mod_array != null)
{
for(int j = 0; j < mod_array.length; j++)
{
int attribute = mod_array[j].getAttribute();
if(attribute == buff_type)
med_obj = inv_contents[i];
}
}
}
}
}
}
if(med_obj != null)
{
if(doctor_bag.isDoctorBag(med_obj))
doctor_bag.setSurrogateState(med_obj, prefix);
}
return med_obj;
}
obj_id findCureDotMedicine(obj_id player, string dot_type)
{
obj_id med_obj = null;
if(!isIdValid(player))
return null;
if(dot_type == null)
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(inventory == null)
return null;
string prefix = "";
obj_id[] inv_contents = utils.getContents(inventory, false);
for(int i = 0; (i < inv_contents.length) && (med_obj==null); i++)
{
prefix = "";
int loop_count = 1;
boolean set_prefix = false;
if(doctor_bag.isDoctorBag(inv_contents[i]))
{
set_prefix = true;
loop_count = doctor_bag.MAX_MEDS;
}
for(int k=0; (k<loop_count) && (med_obj==null); k++)
{
if(set_prefix)
{
prefix = "meds." + k + ".";
if(!hasObjVar(inv_contents[i], "meds."+k))
continue;
}
if(hasObjVar(inv_contents[i], prefix+VAR_HEALING_CURE_DOT))
{
string med_dot_type = getCureDot(inv_contents[i],prefix);
if(dot_type.equals(med_dot_type))
med_obj = inv_contents[i];
}
}
}
if(med_obj != null)
{
if(doctor_bag.isDoctorBag(med_obj))
doctor_bag.setSurrogateState(med_obj, prefix);
}
return med_obj;
}
obj_id findApplyDotMedicine(obj_id player, string dot_type)
{
obj_id med_obj = null;
if(!isIdValid(player))
return null;
if(dot_type == null)
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(inventory == null)
return null;
string prefix = "";
obj_id[] inv_contents = utils.getContents(inventory, false);
for(int i = 0; (i < inv_contents.length) && (med_obj==null); i++)
{
prefix = "";
int loop_count = 1;
boolean set_prefix = false;
if(doctor_bag.isDoctorBag(inv_contents[i]))
{
set_prefix = true;
loop_count = doctor_bag.MAX_MEDS;
}
for(int k=0; (k<loop_count) && (med_obj==null); k++)
{
if(set_prefix)
{
prefix = "meds." + k + ".";
if(!hasObjVar(inv_contents[i], "meds."+k))
continue;
}
if(hasObjVar(inv_contents[i], prefix+VAR_HEALING_APPLY_DOT))
{
string med_dot_type = getApplyDot(inv_contents[i],prefix);
if (dot_type.equals(med_dot_type))
med_obj = inv_contents[i];
}
}
}
if(med_obj != null)
{
if(doctor_bag.isDoctorBag(med_obj))
doctor_bag.setSurrogateState(med_obj, prefix);
}
return med_obj;
}
boolean hasCombatState(obj_id player, int state_type)
{
return false;
}
int findLargestWoundHeal(obj_id patient, obj_id doctor)
{
return -1;
}
int findLargestTendWound(obj_id patient)
{
return -1;
}
int findWorstState(obj_id patient, obj_id doctor)
{
return -1;
}
int stringToAttribute(string attribute_str)
{
int attribute_int = -1;
if (attribute_str.equals("HEALTH")) attribute_int = HEALTH;
if (attribute_str.equals("CONSTITUTION")) attribute_int = CONSTITUTION;
if (attribute_str.equals("ACTION")) attribute_int = ACTION;
if (attribute_str.equals("STAMINA")) attribute_int = STAMINA;
if (attribute_str.equals("MIND")) attribute_int = MIND;
if (attribute_str.equals("WILLPOWER")) attribute_int = WILLPOWER;
if (attribute_str.equals("POISON")) attribute_int = 6; // POISON
if (attribute_str.equals("DISEASE")) attribute_int = 7; // DISEASE
return attribute_int;
}
string attributeToString(int attribute_int)
{
if ((attribute_int < 0) || (attribute_int >= NUM_ATTRIBUTES + 2)) return null;
string[] names = {"HEALTH", "CONSTITUTION", "ACTION", "STAMINA", "MIND", "WILLPOWER", "POISON", "DISEASE"};
return names[attribute_int];
}
int stringToState(string state_str)
{
state_str = state_str.toUpperCase();
int state_int = -1;
if (state_str.equals("STUNNED"))
state_int = STATE_STUNNED;
if (state_str.equals("BLINDED"))
state_int = STATE_BLINDED;
if (state_str.equals("DIZZY"))
state_int = STATE_DIZZY;
if (state_str.equals("INTIMIDATED"))
state_int = STATE_INTIMIDATED;
return state_int;
}
string stateTypeToString(int state_type)
{
if ((state_type < 12)||(state_type > 15))
return null;
string[] names = {"STUNNED", "BLINDED", "DIZZY", "INTIMIDATED"};
return names[state_type - 12];
}
boolean performMedicalHealDamage(obj_id medic, obj_id target, obj_id med_obj, boolean pay_cost)
{
if(!isIdValid(medic))
return false;
if(!isIdValid(target))
return false;
if(!isIdValid(med_obj))
return false;
boolean isRanged = isRangedMedicine(med_obj);
boolean isPetMed = hasObjVar(med_obj, consumable.VAR_CONSUMABLE_PET_MED);
boolean isDroidPetMed = hasObjVar(med_obj, consumable.VAR_CONSUMABLE_DROID_MED);
if(pay_cost)
{
if(!canPayHealingCost(medic, HEAL_TYPE_MEDICAL_DAMAGE, 1.0f))
{
sendMedicalSpam(medic, SID_MIND_TOO_DRAINED, COMBAT_RESULT_MEDICAL);
return false;
}
}
int health_before = getAttrib(target,HEALTH);
if(consumable.consumeItem(medic, target, med_obj))
{
if (pay_cost)
applyHealingCost(medic, HEAL_TYPE_MEDICAL_DAMAGE, 1.0f);
int health_after = getAttrib(target,HEALTH);
int health_delta = health_after - health_before;
int[] attribs = {HEALTH};
int[] delta = {health_delta};
string[] heal_message = assembleHealingMessage(attribs, delta, medic, target, med_obj);
if(heal_message != null)
sendCombatSpamMessageOob(medic, target, heal_message[0], true, false, false, COMBAT_RESULT_MEDICAL);
if((!isPetMed) && (!isDroidPetMed))
{
grantHealingExperience(delta, medic, target, HEAL_TYPE_MEDICAL_DAMAGE);
}
if(medic != target)
{
if (heal_message != null)
sendCombatSpamMessageOob(medic, target, heal_message[1], false, true, false, COMBAT_RESULT_MEDICAL);
pvpHelpPerformed(medic, target);
addHealingKillCredit(medic, target, delta);
}
return true;
}
return false;
}
boolean performMedicalHealDamage(obj_id medic, obj_id target, obj_id med_obj)
{
return performMedicalHealDamage(medic, target, med_obj, true);
}
obj_id[] getHealableTargetsInArea(obj_id medic, location loc, int radius)
{
if(loc == null)
return null;
obj_id[] objects = getCreaturesInRange(loc, radius);
resizeable obj_id[] healable_targets = new obj_id[0];
for(int i = 0; i < objects.length; i++)
{
if(!isPlayer(objects[i]))
{
if(pet_lib.isCreaturePet(objects[i]))
healable_targets = utils.addElement(healable_targets, objects[i]);
}
else
{
if (factions.pvpDoAllowedHelpCheck(medic, objects[i]))
{
healable_targets = utils.addElement(healable_targets, objects[i]);
}
}
}
if (healable_targets.length < 1)
return null;
else
return healable_targets;
}
obj_id[] getAttackableTargetsInArea(obj_id medic, location loc, int radius)
{
if(loc == null)
return null;
obj_id[] objects = getCreaturesInRange(loc, radius);
resizeable obj_id[] attackable_targets = new obj_id[0];
for(int i = 0; i < objects.length; i++)
{
if(isMob(objects[i]))
{
if (factions.pvpDoAllowedAttackCheck(medic, objects[i]))
{
if(!isIncapacitated(objects[i]) && !isDead(objects[i]))
{
if(!pet_lib.isVehiclePet(objects[i]) && !ai_lib.isAndroid(objects[i]) && ai_lib.aiGetNiche(objects[i])!=NICHE_DROID && ai_lib.aiGetNiche(objects[i])!=NICHE_VEHICLE && !vehicle.isDriveableVehicle(objects[i]))
attackable_targets = utils.addElement(attackable_targets, objects[i]);
}
}
}
}
if (attackable_targets.length < 1)
return null;
else
return attackable_targets;
}
boolean applyHealingCost(obj_id player, string heal_type, float modifier)
{
if(!isIdValid(player))
return false;
if(modifier <= 0)
return false;
int mind = getAttrib(player, MIND);
int cost = 0;
if(heal_type.equals(HEAL_TYPE_MEDICAL_DAMAGE))
cost = VAR_HEALDAMAGE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_WOUND))
cost = VAR_HEALWOUND_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_STATE))
cost = VAR_HEALSTATE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_BUFF))
cost = VAR_HEALENHANCE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_REVIVE))
cost = COST_MIND_REVIVE;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_FIRSTAID))
cost = VAR_FIRSTAID_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_POISON))
cost = VAR_CURE_POISON_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_FIRE))
cost = VAR_CURE_FIRE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_CURE_DISEASE))
cost = VAR_CURE_DISEASE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_POISON))
cost = VAR_APPLY_POISON_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_APPLY_DISEASE))
cost = VAR_APPLY_DISEASE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_QUICK_HEAL))
cost = VAR_QUICK_HEAL_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_TEND_WOUND))
cost = VAR_TEND_WOUND_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_TEND_DAMAGE))
cost = VAR_TEND_DAMAGE_COST;
else if(heal_type.equals(HEAL_TYPE_MEDICAL_HEAL_MIND))
cost = VAR_HEAL_MIND_COST;
else
return false;
cost = (int)(cost * modifier);
if(mind < cost)
return false;
return drainAttributes(player, 0, cost);
}
boolean performHealState(obj_id medic, obj_id target, obj_id med_obj)
{
return false;
}
boolean performHealEnhance(obj_id medic, obj_id target, obj_id med_obj)
{
if (medic == null || medic == obj_id.NULL_ID)
return false;
if (target == null || target == obj_id.NULL_ID)
return false;
if (med_obj == null || med_obj == obj_id.NULL_ID)
return false;
// Pay the costs
if (!canPayHealingCost(medic, HEAL_TYPE_MEDICAL_BUFF, 1.0f))
{
LOG("HEALING_MESSAGE_ERROR", medic + " ->Your mind is too drained to do that.");
sendMedicalSpam(medic, SID_MIND_TOO_DRAINED, COMBAT_RESULT_MEDICAL);
return false;
}
if (consumable.consumeItem(medic, target, med_obj))
{
applyHealingCost(medic, HEAL_TYPE_MEDICAL_BUFF, 1.0f);
int[] attribute = {HEALTH};
int duration = 0;
string attribute_string = "";
string objvar_name = "";
int buff_amount = 0;
int old_buff_amount = 0;
string medicinebuff = SCRIPT_VAR_MEDICINE_BUFF;
string medicinerebuff = SCRIPT_VAR_MEDICINE_REBUFF;
int net_buff_amount = 0;
for ( int x = 0; x < attribute.length; x++ )
{
buff_amount = 0;
old_buff_amount = 0;
net_buff_amount = 0;
attribute_string = attributeToString(attribute[x]);
attribute_string = attribute_string.substring(0,1).toUpperCase() + attribute_string.substring(1).toLowerCase();
objvar_name = "healing." + attribute_string.toLowerCase() + "_enhance";
if (utils.hasScriptVar(target, medicinebuff + "."+x))
{
//sendSystemMessageTestingOnly(medic, "You enhance " + getFirstName(target) + "'s " + attribute_string + " by " + net_buff_amount + ".");
//sendSystemMessageTestingOnly(target, getFirstName(medic) + " enhances your " + attribute_string + " by " + net_buff_amount + ".");
//LOG("HEALING_MESSAGE_ERROR", medic + " ->You enhance " + getFirstName(target) + "'s " + attribute_string + " by " + net_buff_amount + ".");
//LOG("HEALING_MESSAGE_ERROR", target + " ->" + getFirstName(medic) + " enhances your " + attribute_string + " by " + net_buff_amount + ".");
buff_amount = utils.getIntScriptVar(target, medicinebuff + "."+x);
utils.removeScriptVar(target, medicinebuff + "."+x);
}
if (utils.hasScriptVar(target, medicinerebuff + "."+x))
{
//sendSystemMessageTestingOnly(medic, "You re-apply " + getFirstName(target) + "'s " + attribute_string + " enhancement.");
//sendSystemMessageTestingOnly(target, getFirstName(medic) + " re-applies your " + attribute_string + " enhancement.");
//LOG("HEALING_MESSAGE_ERROR", medic + " ->You re-apply " + getFirstName(target) + "'s " + attribute_string + " enhancement.");
//LOG("HEALING_MESSAGE_ERROR", target + " ->" + getFirstName(medic) + " re-applies your " + attribute_string + " enhancement.");
old_buff_amount = utils.getIntScriptVar(target, medicinerebuff + "."+x);
utils.removeScriptVar(target, medicinerebuff + "."+x);
}
// The net amount buffed is the amount granted on top of any of the target's previous buffs to this attribute.
net_buff_amount = buff_amount - old_buff_amount;
if (attribute[x] == 9 || attribute[x] == 10)
{
attribute_string += " Resistance";
}
// Grant some experience
if (net_buff_amount > 0)
{
if (x == 0)
{
grantHealingExperience(buff_amount, medic, target, HEAL_TYPE_MEDICAL_BUFF);
}
}
string_id attribute_string_id = new string_id("att_n", attribute_string.toLowerCase());
if (medic != target)
{
prose_package ppYouEnhanceYour = prose.getPackage(SID_YOU_ENHANCE_YOUR_ATT);
prose.setTO(ppYouEnhanceYour, attribute_string_id);
prose.setDI(ppYouEnhanceYour, net_buff_amount);
sendMedicalSpam(medic, ppYouEnhanceYour, COMBAT_RESULT_BUFF);
LOG("HEALING_MESSAGE_ERROR", medic + " ->You enhance your " + attribute_string + " by " + net_buff_amount + ".");
if (net_buff_amount > 0)
{
prose_package ppYouEnhanceTargetAtt = prose.getPackage(SID_YOU_ENHANCE_TARGETS_ATTRIBUTE);
prose.setTT(ppYouEnhanceTargetAtt, target);
prose.setTO(ppYouEnhanceTargetAtt, attribute_string_id);
prose.setDI(ppYouEnhanceTargetAtt, net_buff_amount);
sendMedicalSpam(medic, ppYouEnhanceTargetAtt, COMBAT_RESULT_BUFF);
prose_package ppMedicEnhancesYourAtt = prose.getPackage(SID_MEDIC_ENHANCES_YOUR_ATTRIBUTE);
prose.setTT(ppMedicEnhancesYourAtt, medic);
prose.setTO(ppMedicEnhancesYourAtt, attribute_string_id);
prose.setDI(ppMedicEnhancesYourAtt, net_buff_amount);
sendMedicalSpam(target, ppMedicEnhancesYourAtt, COMBAT_RESULT_BUFF);
LOG("LOG_CHANNEL", medic + " ->You enhance " + getFirstName(target) + "'s " + attribute_string + " by " + net_buff_amount + ".");
LOG("LOG_CHANNEL", target + " ->" + getFirstName(medic) + " enhances your " + attribute_string + " by " + net_buff_amount + ".");
}
else
{
prose_package ppReapplyTarget = prose.getPackage(SID_REAPPLY_ENHANCEMENT_TARGET);
prose.setTT(ppReapplyTarget, target);
prose.setTO(ppReapplyTarget, attribute_string_id);
sendMedicalSpam(medic, ppReapplyTarget, COMBAT_RESULT_BUFF);
prose_package ppReappliesYou = prose.getPackage(SID_REAPPLIES_ENHANCEMENT_YOU);
prose.setTT(ppReappliesYou, medic);
prose.setTO(ppReappliesYou, attribute_string_id);
sendMedicalSpam(target, ppReappliesYou, COMBAT_RESULT_BUFF);
LOG("LOG_CHANNEL", medic + " ->You re-apply " + getFirstName(target) + "'s " + attribute_string + " enhancement.");
LOG("LOG_CHANNEL", target + " ->" + getFirstName(medic) + " re-applies your " + attribute_string + " enhancement.");
}
pvpHelpPerformed(medic, target);
}
else
{
prose_package ppReapplySelf = prose.getPackage(SID_REAPPLY_ENHANCEMENT_SELF);
prose.setTO(ppReapplySelf, attribute_string_id);
sendMedicalSpam(medic, ppReapplySelf, COMBAT_RESULT_BUFF);
LOG("HEALING_MESSAGE_ERROR", medic + " ->You re-apply your " + attribute_string + " enhancement.");
if (net_buff_amount > 0)
{
prose_package ppEnhanceBySelf = prose.getPackage(SID_ENHANCE_ATTRIBUTE_BY_SELF);
prose.setTO(ppEnhanceBySelf, attribute_string_id);
prose.setDI(ppEnhanceBySelf, net_buff_amount);
sendMedicalSpam(medic, ppEnhanceBySelf, COMBAT_RESULT_BUFF);
LOG("LOG_CHANNEL", medic + " ->You enhance your " + attribute_string + " by " + net_buff_amount + ".");
}
}
}
return true;
}
return false;
}
boolean addHealingBuffIcon(obj_id target, int attribute, float duration)
{
if (!isIdValid(target))
return false;
switch(attribute)
{
case HEALTH:
addBuffIcon(target, "medical_enhance_health", duration);
break;
case CONSTITUTION:
addBuffIcon(target, "medical_enhance_constitution", duration);
break;
case ACTION:
addBuffIcon(target, "medical_enhance_action", duration);
break;
case STAMINA:
addBuffIcon(target, "medical_enhance_stamina", duration);
break;
case MIND:
addBuffIcon(target, "performance_enhance_dance_mind", duration);
break;
case WILLPOWER:
addBuffIcon(target, "performance_enhance_music_willpower", duration);
break;
default:
return false;
}
return true;
}
obj_id findPetDamageMed(obj_id player)
{
if(!isIdValid(player))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(!isIdValid(inventory))
return null;
obj_id[] inv_contents = utils.getContents(inventory, false);
if(inv_contents == null || inv_contents.length == 0)
return null;
for(int i = 0; i < inv_contents.length; i++)
{
if(hasObjVar(inv_contents[i],consumable.VAR_CONSUMABLE_MODS))
{
if(hasObjVar(inv_contents[i], consumable.VAR_CONSUMABLE_PET_MED))
{
if(healing.isHealDamageMedicine(inv_contents[i]))
return inv_contents[i];
}
}
}
return null;
}
obj_id findPetVitalityMed(obj_id player)
{
if(!isIdValid(player))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(!isIdValid(inventory))
return null;
obj_id[] inv_contents = utils.getContents(inventory, false);
if(inv_contents == null || inv_contents.length == 0)
return null;
for(int i = 0; i < inv_contents.length; i++)
{
if(hasObjVar(inv_contents[i],consumable.VAR_CONSUMABLE_BASE))
{
if(hasObjVar(inv_contents[i], consumable.VAR_CONSUMABLE_PET_MED))
{
if(hasObjVar(inv_contents[i], "consumable.strength"))
return inv_contents[i];
}
}
}
return null;
}
boolean performTendWoundsFromTool(obj_id medic, obj_id target, int attribute, obj_id medikit)
{
if(!isIdValid(medic))
return false;
if(!isIdValid(target))
return false;
if(!isIdValid(medikit))
return false;
if(medic != target)
{
if(getDistance(medic, target) > consumable.MAX_AFFECT_DISTANCE)
{
sendMedicalSpam(medic, consumable.SID_TARGET_OUT_OF_RANGE, COMBAT_RESULT_OUT_OF_RANGE);
return false;
}
}
if(!isWounded(target, HEALTH))
{
if (medic == target)
sendMedicalSpam(medic, SID_NO_WOUNDS_OF_TYPE_SELF, COMBAT_RESULT_MEDICAL);
else
{
prose_package ppNoWounds = prose.getPackage(SID_NO_WOUNDS_OF_TYPE_TARGET);
prose.setTT(ppNoWounds, target);
sendMedicalSpam(medic, ppNoWounds, COMBAT_RESULT_MEDICAL);
}
return false;
}
float healingCostMod = 0f;
if(hasObjVar(medikit, "medikit.quality"))
{
int medikitQuality = getIntObjVar(medikit, "medikit.quality");
int medikitQualModScratch = (int) (((100-medikitQuality)/2)+50.5);
float medikitQualMod = ((float) (medikitQualModScratch))/100.0f;
healingCostMod = medikitQualMod;
}
else
healingCostMod = 0.9f;
if(!hasCertification(medic, medikit))
{
string_id strSpam = new string_id("medicine_name", "no_proficiency");
sendMedicalSpam(medic, strSpam, COMBAT_RESULT_MEDICAL);
healingCostMod = healingCostMod * 2.0f;
}
if(!applyHealingCost(medic, HEAL_TYPE_MEDICAL_TEND_WOUND, healingCostMod))
{
sendMedicalSpam(medic, SID_NOT_ENOUGH_MIND, COMBAT_RESULT_MEDICAL);
return false;
}
int attrib_before = getWoundedMaxAttrib(target, HEALTH);
float mult = getHealingMultiplier(medic, null, HEAL_TYPE_MEDICAL_TEND_WOUND);
int heal_power = (int)(VAR_TEND_WOUND_BASE_POWER * mult);
int attrib_after = getWoundedMaxAttrib(target, HEALTH);
int attrib_delta = attrib_after - attrib_before;
string attribute_string = attributeToString(HEALTH).toLowerCase();
string_id attribute_string_id = new string_id("att_n", attribute_string.toLowerCase());
if(medic != target)
{
prose_package ppHealAttTarget = prose.getPackage(SID_HEAL_ATTRIBUTE_TARGET);
prose.setTT(ppHealAttTarget, target);
prose.setTO(ppHealAttTarget, attribute_string_id);
prose.setDI(ppHealAttTarget, attrib_delta);
sendMedicalSpam(medic, ppHealAttTarget, COMBAT_RESULT_MEDICAL);
prose_package ppAttHealed = prose.getPackage(SID_ATTRIBUTE_HEALED);
prose.setTT(ppAttHealed, medic);
prose.setTO(ppAttHealed, attribute_string_id);
prose.setDI(ppAttHealed, attrib_delta);
sendMedicalSpam(target, ppAttHealed, COMBAT_RESULT_MEDICAL);
incrementCount(medikit, -1);
grantHealingExperience(attrib_delta, medic, target, HEAL_TYPE_MEDICAL_TEND_WOUND);
pvpHelpPerformed(medic, target);
}
else
{
prose_package ppHealAttribSelf = prose.getPackage(SID_HEAL_ATTRIB_SELF);
prose.setTO(ppHealAttribSelf, attribute_string_id);
prose.setDI(ppHealAttribSelf, attrib_delta);
sendMedicalSpam(medic, ppHealAttribSelf, COMBAT_RESULT_MEDICAL);
incrementCount(medikit, -1);
}
return true;
}
boolean performQuickHealTool(obj_id medic, obj_id target, boolean tend_damage, obj_id medikit)
{
if(!isIdValid(medic))
return false;
if(!isIdValid(target))
return false;
if(medic != target)
{
if(getDistance(medic, target) > consumable.MAX_AFFECT_DISTANCE)
{
sendMedicalSpam(medic, consumable.SID_TARGET_OUT_OF_RANGE, COMBAT_RESULT_OUT_OF_RANGE);
return false;
}
}
float healingCostMod = 0f;
if(hasObjVar(medikit, "medikit.quality"))
{
int medikitQuality = getIntObjVar(medikit, "medikit.quality");
int medikitQualModScratch = (int) (((100-medikitQuality)/2)+50.5);
float medikitQualMod = ((float) (medikitQualModScratch))/100.0f;
healingCostMod = medikitQualMod;
}
else
healingCostMod = 0.9f;
if (!hasCertification(medic, medikit))
{
string_id strSpam = new string_id("medicine_name", "no_proficiency");
sendMedicalSpam(medic, strSpam, COMBAT_RESULT_MEDICAL);
healingCostMod = healingCostMod * 2.0f;
}
if(tend_damage)
{
if(!applyHealingCost(medic, HEAL_TYPE_MEDICAL_TEND_DAMAGE, healingCostMod))
{
sendMedicalSpam(medic, SID_NOT_ENOUGH_MIND, COMBAT_RESULT_MEDICAL);
return false;
}
}
else
{
if(!applyHealingCost(medic, HEAL_TYPE_MEDICAL_QUICK_HEAL, healingCostMod))
{
sendMedicalSpam(medic, SID_NOT_ENOUGH_MIND, COMBAT_RESULT_MEDICAL);
return false;
}
}
if(tend_damage)
{
//int tempDamageWoundCostWillpower = (int) (VAR_TEND_DAMAGE_WOUND_COST * healingCostMod);
//addWound(medic, WILLPOWER, tempDamageWoundCostWillpower);
}
else
{
//int tempQuickHealCostWillpower = (int) (VAR_QUICK_HEAL_WOUND_COST * healingCostMod);
//addWound(medic, WILLPOWER, tempQuickHealCostWillpower);
}
int health_before = getAttrib(target,HEALTH);
float mult;
if(tend_damage)
mult = getHealingMultiplier(medic, null, HEAL_TYPE_MEDICAL_TEND_DAMAGE);
else
mult = getHealingMultiplier(medic, null, HEAL_TYPE_MEDICAL_QUICK_HEAL);
int heal_power;
if(tend_damage)
heal_power = (int)(VAR_TEND_DAMAGE_BASE_POWER * mult);
else
heal_power = (int)(VAR_QUICK_HEAL_BASE_POWER * mult);
attrib_mod am = utils.createHealDamageAttribMod(HEALTH, heal_power);
utils.addAttribMod(target, am);
int health_after = getAttrib(target,HEALTH);
int health_delta = health_after - health_before;
int[] attribs = {HEALTH};
int[] delta = {health_delta};
string[] heal_message = assembleHealingMessage(attribs, delta, medic, target, null);
if(heal_message != null)
sendCombatSpamMessageOob(medic, target, heal_message[0], true, false, false, COMBAT_RESULT_MEDICAL);
if(medic != target)
{
if(heal_message != null)
sendCombatSpamMessageOob(medic, target, heal_message[1], false, true, false, COMBAT_RESULT_MEDICAL);
if (tend_damage)
grantHealingExperience(delta, medic, target, HEAL_TYPE_MEDICAL_TEND_DAMAGE);
else
grantHealingExperience(delta, medic, target, HEAL_TYPE_MEDICAL_QUICK_HEAL);
incrementCount(medikit, -1);
pvpHelpPerformed(medic, target);
addHealingKillCredit(medic, target, delta);
}
return true;
}
boolean isAdvancedTool(obj_id target)
{
if(!isIdValid(target))
return false;
string fullPath = getTemplateName(target);
if(fullPath == null || fullPath.equals(""))
return false;
if(fullPath.indexOf("medikit_tool_advanced") > -1)
return true;
return false;
}
boolean hasCertification(obj_id objPlayer, obj_id objMedikit)
{
if(isAdvancedTool(objMedikit))
{
if(hasObjVar(objMedikit, "medikit.strCertUsed"))
{
string strCommand = getStringObjVar(objMedikit, "medikit.strCertUsed");
if(!hasCommand(objPlayer, strCommand))
return false;
}
else
{
string_id strName = getNameStringId(objMedikit);
if(strName!=null)
{
string strAscii = strName.getAsciiId();
string strCert = "cert_" + strAscii;
if(!hasCommand(objPlayer, strCert))
return false;
}
}
}
return true;
}
boolean isMedikit(obj_id object)
{
if(!isIdValid(object))
return false;
if(hasObjVar(object,"medikit.isMedikit"))
return true;
return false;
}
obj_id findMedikit(obj_id player)
{
if(!isIdValid(player))
return null;
obj_id inventory = getObjectInSlot(player, "inventory");
if(inventory == null)
return null;
obj_id[] inv_contents = utils.getContents(inventory, false);
if(inv_contents == null || inv_contents.length == 0)
return null;
for(int i = 0; i < inv_contents.length; i++)
{
if(isMedikit(inv_contents[i]))
return inv_contents[i];
}
return null;
}
void doHealingAnimationAndEffect(obj_id user, obj_id target)
{
if(user == target)
doAnimationAction(user, "heal_self");
else
doAnimationAction(user, "heal_other");
playClientEffectObj(user, "appearance/pt_heal.prt", target, "");
}
boolean isValidHealTarget(obj_id target)
{
if(!isIdValid(target) || !exists(target) || isInvulnerable(target) || ai_lib.isDroid(target)
|| ai_lib.isAndroid(target) || pet_lib.getPetType(target) == pet_lib.PET_TYPE_FAMILIAR)
{
return false;
}
return true;
}
boolean isValidHealTarget(obj_id healer, obj_id target)
{
if(!isIdValid(target) || !exists(target) || isInvulnerable(target) || pet_lib.getPetType(target) == pet_lib.PET_TYPE_FAMILIAR)
{
return false;
}
// If the source of the heal is a droid, then that droid can heal another droid (repair).
if(ai_lib.isDroid(healer) || ai_lib.isAndroid(healer))
{
return true;
}
if(ai_lib.isDroid(target) || ai_lib.isAndroid(target))
{
return false;
}
return true;
}
void applyLifeSiphonHeal(obj_id attacker, obj_id defender, int damage, float percentToHeal, string actionName)
{
applyLifeSiphonHeal(attacker, defender, damage, percentToHeal, actionName, false);
}
void applyLifeSiphonHeal(obj_id attacker, obj_id defender, int damage, float percentToHeal, string actionName, boolean healMaster)
{
if (percentToHeal > 0)
{
int damageToHeal = Math.round(damage * percentToHeal);
//All operations on the attacker as this is a drain effect.
damageToHeal = getHealingAfterReductions(attacker, attacker, damageToHeal);
damageToHeal = getTargetHealingBonus(attacker, attacker, damageToHeal);
healDamage(attacker, attacker, HEALTH, damageToHeal);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("healing", "siphon_fly"));
pp = prose.setDI(pp, damageToHeal);
pp = prose.setTO(pp, "Health Leech");
if (actionName.endsWith("master"))
healMaster = true;
if (isPlayer(attacker))
prose.setTO(pp, "Drain");
if (isPlayer(attacker))
{
showFlyTextPrivateProseWithFlags(attacker/*getSelf()*/, attacker , pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
string_id actionStringId = new string_id("cmd_n", actionName);
prose_package cp = new prose_package();
cp = prose.setStringId(cp, new string_id("cbt_spam", "drain_hit"));
cp = prose.setTU(cp, attacker);
cp = prose.setTT(cp, defender);
cp = prose.setDI(cp, damageToHeal);
sendCombatSpamMessageProse(attacker, defender, cp, true, true, true, COMBAT_RESULT_MEDICAL);
}
else if(beast_lib.isBeast(attacker))
{
showFlyTextPrivateProseWithFlags(attacker/*getSelf()*/, getMaster(attacker) , pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
}
if (isPlayer(defender))
showFlyTextPrivateProseWithFlags(attacker/*getSelf()*/, defender , pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
if (isIdValid(getMaster(attacker)))
{
attacker = getMaster(attacker);
if (healMaster && exists(attacker) && !isDead(attacker))
{
damageToHeal = getHealingAfterReductions(attacker, attacker, damageToHeal);
damageToHeal = getTargetHealingBonus(attacker, attacker, damageToHeal);
pp = prose.setDI(pp, damageToHeal);
healDamage(attacker, attacker, HEALTH, damageToHeal);
if (isPlayer(attacker))
{
showFlyTextPrivateProseWithFlags(attacker, attacker , pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
}
if (isPlayer(defender))
showFlyTextPrivateProseWithFlags(attacker, defender , pp, 2.0f, colors.SEAGREEN, FLY_TEXT_FLAG_IS_HEAL);
}
}
}
}
int doDiminishingReturns(int toHeal, obj_id medic)
{
float rightNow = getGameTime();
if(!utils.hasScriptVar(medic, "healing.diminishing_returns.last_heal_time"))
{
utils.setScriptVar(medic, "healing.diminishing_returns.last_heal_time", rightNow);
utils.setScriptVar(medic, "healing.diminishing_returns.heal_total", toHeal);
buff.applyBuff(medic, "heal_diminishing_returns_1");
return toHeal;
}
float lastHealTime = utils.getFloatScriptVar(medic, "healing.diminishing_returns.last_heal_time");
// We're outside the DR timer
if(rightNow - lastHealTime > 30f)
{
utils.setScriptVar(medic, "healing.diminishing_returns.last_heal_time", rightNow);
utils.setScriptVar(medic, "healing.diminishing_returns.heal_total", toHeal);
buff.applyBuff(medic, "heal_diminishing_returns_1");
return toHeal;
}
int healTotal = utils.getIntScriptVar(medic, "healing.diminishing_returns.heal_total");
int reductionThreshold = 25000;
if(healTotal <= reductionThreshold)
{
utils.setScriptVar(medic, "healing.diminishing_returns.last_heal_time", rightNow);
utils.setScriptVar(medic, "healing.diminishing_returns.heal_total", toHeal + healTotal);
buff.applyBuff(medic, "heal_diminishing_returns_1");
return toHeal;
}
// Dun dun dun! Otherwise, reduce the amount healed.
float healTotalFloat = (float)healTotal;
float toHealFloat = (float)toHeal;
float originalHeal = toHeal;
float diminishedAmount = 1.0f;
healTotalFloat -= reductionThreshold;
diminishedAmount = healTotalFloat / (100f + (healTotalFloat / 45f)) / 100.0f;
toHealFloat = toHealFloat * (1.0f - diminishedAmount);
toHeal = (int)toHealFloat;
utils.setScriptVar(medic, "healing.diminishing_returns.last_heal_time", rightNow);
utils.setScriptVar(medic, "healing.diminishing_returns.heal_total", toHeal + healTotal);
// Throw an icon on there.
float healNerfRatio = toHealFloat/originalHeal;
if(healNerfRatio > .70f)
{
buff.applyBuff(medic, "heal_diminishing_returns_2");
}
else if(healNerfRatio > .35f)
{
buff.applyBuff(medic, "heal_diminishing_returns_3");
}
else
{
buff.applyBuff(medic, "heal_diminishing_returns_4");
}
return toHeal;
}