mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-31 00:15:54 -04:00
497 lines
14 KiB
Plaintext
497 lines
14 KiB
Plaintext
|
|
/***** INCLUDES ********************************************************/
|
|
|
|
include library.utils;
|
|
include java.util.Enumeration;
|
|
include java.lang.Integer;
|
|
include library.combat;
|
|
include library.jedi;
|
|
|
|
/***** CONSTANTS *******************************************************/
|
|
|
|
const int DEFAULT_USE_COUNT = 500;
|
|
const string VAR_POWERUP_BASE = "powerup";
|
|
const string SCRIPT_WEAPON = VAR_POWERUP_BASE + ".weapon";
|
|
|
|
|
|
const string VAR_POWERUP_USES_LEFT = VAR_POWERUP_BASE + ".usesLeft";
|
|
const string VAR_POWERUP_IS_ACTIVE = VAR_POWERUP_BASE + ".isActive";
|
|
const string VAR_POWERUP_EFFECT = VAR_POWERUP_BASE + ".effect";
|
|
const string VAR_POWERUP_EFFICIENCY = VAR_POWERUP_BASE + ".efficiency";
|
|
const string VAR_POWERUP_DAMAGE = VAR_POWERUP_BASE + ".damage";
|
|
const string VAR_POWERUP_SPEED = VAR_POWERUP_BASE + ".speed";
|
|
const string VAR_POWERUP_ACCURACY = VAR_POWERUP_BASE + ".accuracy";
|
|
const string VAR_POWERUP_ACTION = VAR_POWERUP_BASE + ".actionCost";
|
|
const string VAR_POWERUP_WOUND = VAR_POWERUP_BASE + ".wound";
|
|
const string VAR_POWERUP_DECAY_CHANCE = VAR_POWERUP_BASE + ".decayChance";
|
|
const string VAR_POWERUP_DECAY_AMOUNT = VAR_POWERUP_BASE + ".decayAmount";
|
|
const string VAR_POWERUP_ELEMENTAL_DAMAGE = VAR_POWERUP_BASE + ".elementalDamage";
|
|
const string VAR_POWERUP_TYPE = "powerupType";
|
|
|
|
const int CHANCE_TO_DECAY = 75; // chance / 100 to decay each shot/hit
|
|
const int TYPE_MELEE = 1;
|
|
const int TYPE_RANGED = 2;
|
|
const int TYPE_GRENADE = 3;
|
|
|
|
const string STF = "powerup";
|
|
|
|
const string_id PROSE_POWERUP_APPLY = new string_id(STF, "prose_pup_apply");
|
|
const string_id PROSE_POWERUP_EXPIRE = new string_id(STF, "prose_pup_expire");
|
|
const string_id PROSE_ALREADY_POWERED = new string_id(STF, "prose_already_powered");
|
|
const string_id PROSE_APPLY_RESTRICTED = new string_id(STF, "prose_apply_restricted");
|
|
|
|
|
|
/***** FUNCTIONS *******************************************************/
|
|
void getWeaponAttributes (obj_id player, obj_id weapon, string[] names, string[] attribs, boolean forWeapon)
|
|
{
|
|
int idx = utils.getValidAttributeIndex(names);
|
|
if(idx == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
java.text.DecimalFormat percentFormat = new java.text.DecimalFormat("+ %##.##;- %##.##");
|
|
java.text.DecimalFormat intFormat = new java.text.DecimalFormat("+ ##.##;- ##.##");
|
|
|
|
java.text.DecimalFormat formatter = forWeapon ? intFormat : percentFormat;
|
|
|
|
|
|
names[idx] = "cat_pup.pup_uses";
|
|
attribs[idx] = Integer.toString(getIntObjVar(weapon, powerup.VAR_POWERUP_USES_LEFT));
|
|
idx++;
|
|
|
|
obj_var_list ovl = getObjVarList(weapon, powerup.VAR_POWERUP_BASE);
|
|
if(ovl != null)
|
|
{
|
|
int numItems = ovl.getNumItems();
|
|
for(int i = 0; i < numItems; i++)
|
|
{
|
|
obj_var ov = ovl.getObjVar(i);
|
|
string name = ov.getName();
|
|
string varpath = powerup.VAR_POWERUP_BASE + "." + name;
|
|
float mod = getFloatObjVar(weapon, varpath);
|
|
|
|
string log;
|
|
//LOG("powerup", "Attribute: " + name + "/" + mod + (penalty?"/penalty":"/bonus"));
|
|
|
|
// Damage
|
|
if(name.equals("damage"))
|
|
{
|
|
names[idx] = "cat_pup.pup_damage"; // "Damage Modifier"
|
|
attribs[idx] = formatter.format(mod);
|
|
}
|
|
|
|
// Speed
|
|
else if(name.equals("speed"))
|
|
{
|
|
names[idx] = "cat_pup.pup_speed"; // "Attack Speed Modifier"
|
|
attribs[idx] = formatter.format(mod);
|
|
}
|
|
|
|
// Accuracy
|
|
else if(name.equals("accuracy"))
|
|
{
|
|
names[idx] = "cat_pup.pup_accuracy"; // "Accuracy Modifier"
|
|
attribs[idx] = intFormat.format(mod);
|
|
}
|
|
|
|
// Wounds
|
|
else if(name.equals("wound"))
|
|
{
|
|
names[idx] = "cat_pup.pup_wound"; // "Wound Modifier"
|
|
attribs[idx] = formatter.format(mod);
|
|
}
|
|
|
|
// Elemental Damage
|
|
else if(name.equals("elementalDamage"))
|
|
{
|
|
names[idx] = "cat_pup.pup_elemental"; // "Elemental Damage Modifier"
|
|
attribs[idx] = formatter.format(mod);
|
|
}
|
|
|
|
// Action Cost
|
|
else if(name.equals("actionCost"))
|
|
{
|
|
names[idx] = "cat_pup.pup_action"; // "Action Cost Modifier"
|
|
attribs[idx] = formatter.format(mod);
|
|
}
|
|
else
|
|
{
|
|
idx--; // need to decrement if its not something we want to display because we always increment during loop
|
|
}
|
|
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean hasPowerUpInstalled(obj_id weapon)
|
|
{
|
|
return hasObjVar(weapon, VAR_POWERUP_BASE);
|
|
}
|
|
|
|
// Tests to see if a weapon is powered up and whether or not it should decay
|
|
boolean powerUpDecay(obj_id weapon)
|
|
{
|
|
if(!hasPowerUpInstalled(weapon))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return (rand(1, 100) < CHANCE_TO_DECAY);
|
|
}
|
|
|
|
/* for use if/when powerup (de)activation is implemented
|
|
boolean isPowerUpActive(obj_id weapon)
|
|
{
|
|
if(!hasObjVar(weapon, VAR_POWERUP_IS_ACTIVE))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return getBooleanObjVar(weapon, VAR_POWERUP_IS_ACTIVE);
|
|
}
|
|
|
|
void togglePoweredUp(obj_id weapon)
|
|
{
|
|
if(!hasPowerUpInstalled(weapon))
|
|
{
|
|
return;
|
|
}
|
|
|
|
setObjVar(weapon, VAR_POWERUP_IS_ACTIVE, !getBooleanObjVar(weapon, VAR_POWERUP_IS_ACTIVE));
|
|
}
|
|
*/
|
|
|
|
|
|
boolean applyPowerup(obj_id player, obj_id powerup, obj_id target)
|
|
{
|
|
|
|
if(!isIdValid(player) || !isIdValid(powerup) || !isIdValid(target) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(!hasObjVar(powerup, VAR_POWERUP_BASE))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(hasPowerUpInstalled(target))
|
|
{
|
|
prose_package ppAlreadyPowered = prose.getPackage(PROSE_ALREADY_POWERED, target);
|
|
sendSystemMessageProse(player, ppAlreadyPowered);
|
|
return false;
|
|
}
|
|
|
|
int iGot = getGameObjectType(powerup);
|
|
if(!isGameObjectTypeOf(iGot, GOT_powerup_weapon) )
|
|
{
|
|
LOG("powerup", "GOT Failure");
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_failed_type_unknown")); // faulty powerup
|
|
return false;
|
|
}
|
|
|
|
if(jedi.isLightsaber(target))
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_fail_saber")); // cant apply to saber
|
|
return false;
|
|
}
|
|
|
|
if(static_item.isStaticItem(target))
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_fail_static")); // cant apply to static Items
|
|
return false;
|
|
}
|
|
|
|
if(!hasObjVar(powerup, VAR_POWERUP_TYPE))
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_failed_type_unknown")); // faulty powerup
|
|
LOG("powerup", VAR_POWERUP_TYPE + " objvar failure");
|
|
return false;
|
|
}
|
|
|
|
int powerupType = getIntObjVar(powerup, VAR_POWERUP_TYPE);
|
|
LOG("powerup", "Type=" + powerupType);
|
|
switch(powerupType)
|
|
{
|
|
case TYPE_MELEE:
|
|
if(!combat.isMeleeWeapon(target))
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_fail_not_melee")); // not a melee weapon
|
|
LOG("powerup", "Melee weapon failure");
|
|
return false;
|
|
}
|
|
break;
|
|
case TYPE_RANGED:
|
|
if(!combat.isRangedWeapon(target))
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_fail_not_ranged")); // not a ranged weapon
|
|
LOG("powerup", "Ranged weapon failure");
|
|
return false;
|
|
}
|
|
break;
|
|
case TYPE_GRENADE:
|
|
int weaponType = getWeaponType(target);
|
|
if(weaponType != WEAPON_TYPE_THROWN)
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_fail_not_grenade")); // not a grenade
|
|
LOG("powerup", "Grenade weapon failure");
|
|
return false;
|
|
}
|
|
break;
|
|
default:
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_failed_type_unknown")); // faulty powerup
|
|
LOG("powerup", "Default faulure");
|
|
return false;
|
|
}
|
|
|
|
// special case the elemental damage modifiers
|
|
string template = getTemplateName(powerup);
|
|
if(template.equals("object/tangible/powerup/weapon/ranged_power.iff") || template.equals("object/tangible/powerup/weapon/melee_element_dispursal_tuner.iff"))
|
|
{
|
|
int elementalDamage = getWeaponElementalValue(target);
|
|
if(elementalDamage < 1)
|
|
{
|
|
sendSystemMessage(player, new string_id("powerup_d", "apply_fail_no_elemental")); // wrong powerup
|
|
LOG("powerup", "Elemental failure");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
float speedMod = 0;
|
|
float accuracyMod = 0;
|
|
float woundMod = 0;
|
|
float actionMod = 0;
|
|
float damageMod = 0;
|
|
float elementalMod = 0;
|
|
|
|
obj_var_list ovl = getObjVarList(powerup, VAR_POWERUP_BASE);
|
|
if(ovl != null)
|
|
{
|
|
int numItems = ovl.getNumItems();
|
|
for(int i = 0; i < numItems; i++)
|
|
{
|
|
obj_var ov = ovl.getObjVar(i);
|
|
string name = ov.getName();
|
|
|
|
string varpath = VAR_POWERUP_BASE + "." + name;
|
|
|
|
if(name.equals("speed"))
|
|
{
|
|
speedMod = ov.getFloatData();
|
|
}
|
|
|
|
else if(name.equals("damage"))
|
|
{
|
|
damageMod = ov.getFloatData();
|
|
}
|
|
|
|
else if(name.equals("accuracy"))
|
|
{
|
|
accuracyMod = ov.getFloatData();
|
|
}
|
|
|
|
else if(name.equals("wound"))
|
|
{
|
|
woundMod = ov.getFloatData();
|
|
}
|
|
|
|
else if(name.equals("elementalDamage"))
|
|
{
|
|
elementalMod = ov.getFloatData();
|
|
}
|
|
|
|
else if(name.equals("actionCost"))
|
|
{
|
|
actionMod = ov.getFloatData();
|
|
}
|
|
}
|
|
}
|
|
|
|
LOG("powerup", "----------- Applying powerup ----------");
|
|
|
|
// apply the mods and store the difference between old and new values. That way, if something else should modify
|
|
// the weapon after we apply the powerup, we only undo what we applied here when the powerup is removed
|
|
if(speedMod != 0)
|
|
{
|
|
float oldSpeed = getWeaponAttackSpeed(target);
|
|
float newSpeed = oldSpeed + (oldSpeed * speedMod);
|
|
|
|
LOG("powerup", "oldSpeed=" + oldSpeed + ", newSpeed=" + newSpeed + ", diff=" + (oldSpeed-newSpeed));
|
|
setWeaponAttackSpeed(target, newSpeed);
|
|
setObjVar(target, VAR_POWERUP_SPEED, oldSpeed-newSpeed);
|
|
}
|
|
|
|
if(accuracyMod != 0)
|
|
{
|
|
float oldAccuracy = getWeaponAccuracy(target);
|
|
float newAccuracy = oldAccuracy + accuracyMod; // accuracy is the only stat thats not percentage based because not all weapons may have an accuracy
|
|
|
|
LOG("powerup", "oldAccuracy=" + oldAccuracy + ", newAccuracy=" + newAccuracy + ", diff=" + (newAccuracy-((int)oldAccuracy)));
|
|
setWeaponAccuracy(target, (int)newAccuracy);
|
|
setObjVar(target, VAR_POWERUP_ACCURACY, newAccuracy-((int)oldAccuracy));
|
|
}
|
|
|
|
if(woundMod != 0)
|
|
{
|
|
float oldWounds = getWeaponWoundChance(target);
|
|
float newWounds = oldWounds + (oldWounds * woundMod);
|
|
|
|
LOG("powerup", "oldWounds=" + oldWounds + ", newWounds=" + newWounds + ", diff=" + (newWounds-oldWounds));
|
|
setWeaponWoundChance(target, newWounds);
|
|
setObjVar(target, VAR_POWERUP_WOUND, newWounds-oldWounds);
|
|
}
|
|
|
|
if(actionMod != 0)
|
|
{
|
|
float oldAction = getWeaponAttackCost(target);
|
|
float newAction = (float)Math.floor(oldAction + (oldAction * actionMod));
|
|
|
|
LOG("powerup", "oldAction=" + oldAction + ", newAction=" + newAction + ", diff=" + (newAction-oldAction));
|
|
setWeaponAttackCost(target, (int)newAction);
|
|
setObjVar(target, VAR_POWERUP_ACTION, newAction-oldAction);
|
|
}
|
|
|
|
if(damageMod != 0)
|
|
{
|
|
int oldMinDamage = getWeaponMinDamage(target);
|
|
int oldMaxDamage = getWeaponMaxDamage(target);
|
|
int newMinDamage = (int)Math.floor(oldMinDamage + (oldMinDamage * damageMod));
|
|
|
|
if(newMinDamage < 1)
|
|
{
|
|
newMinDamage = 1;
|
|
}
|
|
|
|
// need to store delta as a float because the Attributes formatter has a fit if its an int
|
|
float delta = (int)(newMinDamage - oldMinDamage);
|
|
int newMaxDamage = oldMaxDamage + (int)delta;
|
|
|
|
|
|
LOG("powerup", "oldMinDamage=" + oldMinDamage + ", newMinDamage=" + newMinDamage + ", delta=" + delta);
|
|
LOG("powerup", "oldMaxDamage=" + oldMaxDamage + ", newMaxDamage=" + newMaxDamage + ", delta=" + delta);
|
|
|
|
setWeaponMinDamage(target, newMinDamage);
|
|
setWeaponMaxDamage(target, newMaxDamage);
|
|
setObjVar(target, VAR_POWERUP_DAMAGE, delta);
|
|
weapons.setWeaponData(target);
|
|
}
|
|
|
|
if(elementalMod != 0)
|
|
{
|
|
float oldEDamage = getWeaponElementalValue(target);
|
|
float newEDamage = (int)Math.floor(oldEDamage + (oldEDamage * elementalMod));
|
|
|
|
// need to store delta as a float because the Attributes formatter has a fit if its an int
|
|
float delta = (int)(newEDamage-oldEDamage);
|
|
|
|
LOG("powerup", "oldEDamage=" + oldEDamage+ ", newEDamage=" + newEDamage + ", diff=" + delta);
|
|
setWeaponElementalValue(target, (int)newEDamage);
|
|
setObjVar(target, VAR_POWERUP_ELEMENTAL_DAMAGE, newEDamage-((int)oldEDamage));
|
|
}
|
|
|
|
LOG("powerup", "----------- Done Applying powerup ----------");
|
|
|
|
destroyObject(powerup);
|
|
attachScript(target, SCRIPT_WEAPON);
|
|
|
|
prose_package ppApply = prose.getPackage(PROSE_POWERUP_APPLY, powerup, target);
|
|
sendSystemMessageProse(player, ppApply);
|
|
|
|
return true;
|
|
}
|
|
|
|
boolean cleanupWeaponPowerup(obj_id weapon)
|
|
{
|
|
LOG("powerup", "Cleaning Up " + weapon);
|
|
obj_var_list ovl = getObjVarList(weapon, VAR_POWERUP_BASE);
|
|
if(ovl != null)
|
|
{
|
|
int numItems = ovl.getNumItems();
|
|
for ( int i = 0; i < numItems; i++ )
|
|
{
|
|
obj_var ov = ovl.getObjVar(i);
|
|
string name = ov.getName();
|
|
|
|
string varpath = VAR_POWERUP_BASE + "." + name;
|
|
|
|
if(name.equals("speed"))
|
|
{
|
|
float curSpeed = getWeaponAttackSpeed(weapon);
|
|
float speedDiff = getFloatObjVar(weapon, varpath);
|
|
setWeaponAttackSpeed(weapon, curSpeed + speedDiff);
|
|
}
|
|
else if(name.equals("damage"))
|
|
{
|
|
int curMinDmg = getWeaponMinDamage(weapon);
|
|
float dmgDiff = getFloatObjVar(weapon, varpath);
|
|
setWeaponMinDamage(weapon, curMinDmg - (int)dmgDiff);
|
|
|
|
int curMaxDmg = getWeaponMaxDamage(weapon);
|
|
setWeaponMaxDamage(weapon, curMaxDmg - (int)dmgDiff);
|
|
}
|
|
else if ( name.equals("accuracy") )
|
|
{
|
|
int curAcc = getWeaponAccuracy(weapon);
|
|
float accDiff = getFloatObjVar(weapon, varpath);
|
|
setWeaponAccuracy(weapon, curAcc - (int)accDiff);
|
|
}
|
|
else if ( name.equals("wound") )
|
|
{
|
|
float curWound = getWeaponWoundChance(weapon);
|
|
float woundDiff = getFloatObjVar(weapon, varpath);
|
|
LOG("powerup", "Reverting wound: curWound=" + curWound + ", woundDiff=" + woundDiff +", newWound=" + (curWound-woundDiff));
|
|
setWeaponWoundChance(weapon, curWound - woundDiff);
|
|
}
|
|
else if ( name.equals("elementalDamage") )
|
|
{
|
|
int curEDmg = getWeaponElementalValue(weapon);
|
|
float eDmgDiff = getFloatObjVar(weapon, varpath);
|
|
setWeaponElementalValue(weapon, curEDmg - (int)eDmgDiff);
|
|
}
|
|
else if ( name.equals("actionCost") )
|
|
{
|
|
float curAction = getWeaponAttackCost(weapon);
|
|
float actionDiff = getFloatObjVar(weapon, varpath);
|
|
setWeaponAttackCost(weapon, (int)curAction - (int)actionDiff);
|
|
}
|
|
}
|
|
}
|
|
weapons.setWeaponData(weapon);
|
|
removeObjVar(weapon, powerup.VAR_POWERUP_BASE);
|
|
clearCondition(weapon, CONDITION_MAGIC_ITEM);
|
|
detachScript(weapon, SCRIPT_WEAPON);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void decrementUseCounter(obj_id target)
|
|
{
|
|
if(!isIdValid(target))
|
|
{
|
|
return;
|
|
}
|
|
|
|
int cnt = getIntObjVar(target, VAR_POWERUP_USES_LEFT);
|
|
cnt--;
|
|
|
|
if(cnt < 1)
|
|
{
|
|
cleanupWeaponPowerup(target);
|
|
|
|
obj_id owner = getOwner(target);
|
|
if ( !isIdValid(owner) )
|
|
return;
|
|
|
|
prose_package ppExpire = prose.getPackage(PROSE_POWERUP_EXPIRE, target);
|
|
sendSystemMessageProse(owner, ppExpire);
|
|
return;
|
|
}
|
|
|
|
setObjVar(target, VAR_POWERUP_USES_LEFT, cnt);
|
|
}
|
|
|