Files
dsrc/sku.0/sys.server/compiled/game/script/library/space_combat.scriptlib
T

6318 lines
204 KiB
Plaintext

// this is the combat scriptlib for the space expansion
include library.badge;
include library.buff;
include library.callable;
include library.factions;
include library.groundquests;
include library.scheduled_drop;
include library.ship_ai;
include library.smuggler;
include library.space_crafting;
include library.space_flags;
include library.space_utils;
include library.utils;
include library.xp;
const float SPACE_DEATH_DELAY = 10.0f; // death camera delay
// for damage interior stuff.. purely visual. dont touch though
const int CHASSIS = 1;
const int COMPONENT = 2;
const int SHIELD = 3;
const int ARMOR = 4;
const int LIGHT = 1;
const int HEAVY = 2;
const int ALL_WEAPONS = -1;
const float GROUND_XP_PERCENT = 0.01f;
const int[] MANDATORY_COMPONENTS = {
ship_chassis_slot_type.SCST_reactor,
ship_chassis_slot_type.SCST_engine
};
const int[] WEAPON_SLOTS = {
ship_chassis_slot_type.SCST_weapon_0,
ship_chassis_slot_type.SCST_weapon_1,
ship_chassis_slot_type.SCST_weapon_2,
ship_chassis_slot_type.SCST_weapon_3,
ship_chassis_slot_type.SCST_weapon_4,
ship_chassis_slot_type.SCST_weapon_5,
ship_chassis_slot_type.SCST_weapon_6,
ship_chassis_slot_type.SCST_weapon_7
};
const float MINIMUM_DAMAGE_THRESHOLD = .05f; // you do less than this, you get NOTHING! NO CREDIT, NO LOOT, NADA!
const float MINIMUM_EFFICIENCY = .10f;
const float NO_CHANGE = -1f;
//const int SHIP = -1; // represents the ship being targeted instead of a specific component slot
const int SHIP = ship_chassis_slot_type.SCST_num_types;
const int FRONT = 0; // just some consts for directional fire
const int BACK = 1;
const int NONE = -2;
const int NOVA_ORION_RESOURCE_MIN = 1;
const int NOVA_ORION_RESOURCE_MAX = 15;
const int NOVA_ORION_RESOURCE_CHANCE = 25;
const int NOVA_ORION_BUFF_MIDLITHE_BONUS = 5;
const int NOVA_ORION_BUFF_COLLECTIBLES_BONUS = 2;
const string NOVA_ORION_RESOURCE = "item_nova_orion_space_resource_01_01";
const string SHIP_DATATABLE = "datatables/space_mobile/space_mobile.iff";
const float DROID_VOCALIZE_DELAY_CONST = 1.0f; //increase this value to generally increase the amount of time between low priority astromech vocalizations
const string DROID_VOCALIZE_DATATABLE = "datatables/space_combat/droid_vocalizations.iff";
const int AVERAGE_COMMAND_SUCCESS_RATE = 65; //The percenatage of the time that the player should moderately succeed at an average task.
const int FIRST_WEAPON = ship_chassis_slot_type.SCST_weapon_first;
const int LAST_WEAPON = ship_chassis_slot_type.SCST_weapon_last;
const string PIRATE_EQUIPMENT_DATATABLE = "datatables/space_command/pirate_ship_table.iff";
const string PIRATE_EQUIPMENT_AA = "PIRATE_EQUIPMENT_AA";
const string PIRATE_EQUIPMENT_A = "PIRATE_EQUIPMENT_A";
const string PIRATE_EQUIPMENT_B = "PIRATE_EQUIPMENT_B";
const string PIRATE_EQUIPMENT_C = "PIRATE_EQUIPMENT_C";
const string PIRATE_EQUIPMENT_D = "PIRATE_EQUIPMENT_D";
const int NPC_DAMAGE_MULTIPLIER = 4;
const string_id SID_DISABLED = new string_id("space/space_interaction", "disabled");
// Collections Table
const string SPACE_COLLECTIONS_LOOT_TABLE = "datatables/space_loot/space_collection_loot.iff";
void addToCombatDamage(obj_id objAttacker, obj_id objDefender, int intDamage)
{
resizeable obj_id[] objAttackers = utils.getResizeableObjIdArrayLocalVar(objDefender, "damage.objAttackers");
resizeable int[] intDamageDone = utils.getResizeableIntArrayLocalVar(objDefender, "damage.intDamageDone");
int intIndex = utils.getElementPositionInArray(objAttackers, objAttacker);
if(intIndex < 0)
{
objAttackers = utils.addElement(objAttackers, objAttacker);
intDamageDone = utils.addElement(intDamageDone, intDamage);
utils.setLocalVar(objDefender, "damage.objAttackers", objAttackers);
utils.setLocalVar(objDefender, "damage.intDamageDone", intDamageDone);
return;
}
else
{
intDamageDone[intIndex] = intDamageDone[intIndex] + intDamage;
utils.setLocalVar(objDefender, "damage.intDamageDone", intDamageDone);
}
return;
}
void targetDestroyed(obj_id objTarget)
{
// called when something is blowed up.
// so we check to see where we are
dictionary dctParams = new dictionary();
////////LOG("space", "Notifying "+objTarget+" objectDestroyed");
space_utils.notifyObject(objTarget, "objectDestroyed", dctParams);
return;
}
// need to handle group differentaitaiotn
// group differentiatoin needs to track
// notification of "targeted objects"
// do we just use
// DROIDS
// Normalize all components to their values prior to a droid command.
void normalizeAllComponents(obj_id objShip)
{
string[] normalizeList = { "weapons_normalize", "engine_normalize", "shields_normalize", "reactor_normalize", "weapcap_equalize" };
for(int i = 0; i < normalizeList.length; i++)
{
space_combat.unrestrictedDroidCommand(objShip, normalizeList[i]);
}
}
// This function does no sanity checking to check if the droid interface is installed.
// performDroidCommands() is for sanity checking and messaging.
void unrestrictedDroidCommand(obj_id objShip, string strCommand)
{
if(!isIdValid(objShip) || !exists(objShip))
{
return;
}
dictionary dctCommandInfo = dataTableGetRow("datatables/space_combat/droid_commands.iff", strCommand);
if(dctCommandInfo == null)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.performDroidCommands - FAILED TO GET COMMAND INFO DICTIONARY. STRING NOT FOUND WAS:" + strCommand);
return;
}
string strClientEffect = dctCommandInfo.getString("strClientEffect");
string strStringId = dctCommandInfo.getString("strStringId");
int intComponentToModify = dctCommandInfo.getInt("intComponentToModify");
float fltEnergyEfficiency = dctCommandInfo.getFloat("fltEnergyEfficiency");
float fltGeneralEfficiency = dctCommandInfo.getFloat("fltGeneralEfficiency");
float fltRepairMin = dctCommandInfo.getFloat("fltRepairMin");
float fltRepairMax = dctCommandInfo.getFloat("fltRepairMax");
float fltBaseDelay = dctCommandInfo.getFloat("fltBaseDelay");
float fltRepairKitConsumed = dctCommandInfo.getFloat("fltRepairKitConsumed");
float fltCountermeasureCapacitorCost = dctCommandInfo.getFloat("fltCountermeasureCapacitorCost");
float fltCountermeasureShieldCost = dctCommandInfo.getFloat("fltCountermeasureShieldCost");
float fltFrontToBackShieldReinforcePercentage = dctCommandInfo.getFloat("fltFrontToBackShieldReinforcePercentage");
float fltBackToFrontShieldReinforcePercentage = dctCommandInfo.getFloat("fltBackToFrontShieldReinforcePercentage");
float fltCapacitorReinforcePercentage = dctCommandInfo.getFloat("fltCapacitorReinforcePercentage");
float fltMissileSavingThrow = dctCommandInfo.getFloat("fltMissileSavingThrow");
string strMessageHandlerOnPlayer = dctCommandInfo.getString("strMessageHandlerOnPlayer");
float fltDamageToComponent = dctCommandInfo.getFloat("fltDamageToComponent");
float fltFrontShieldRatio = dctCommandInfo.getFloat("fltFrontShieldRatio");
if((intComponentToModify != NONE) && (intComponentToModify != ALL_WEAPONS))
{
if(!isShipSlotInstalled(objShip, intComponentToModify))
{
return;
}
if(fltDamageToComponent > 0)
{
float fltCurrentHitpoints = getShipComponentHitpointsCurrent(objShip, intComponentToModify);
float fltCurrentArmorHitpoints = getShipComponentArmorHitpointsCurrent(objShip, intComponentToModify);
fltCurrentArmorHitpoints = fltCurrentArmorHitpoints - fltDamageToComponent;
if(fltCurrentArmorHitpoints < 0)
{
float fltRemainingDamage = Math.abs(fltCurrentArmorHitpoints);
fltCurrentHitpoints = fltCurrentHitpoints - fltRemainingDamage;
if(fltCurrentHitpoints < 0)
{
return;
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, intComponentToModify, 0);
setShipComponentHitpointsCurrent(objShip, intComponentToModify, fltCurrentHitpoints);
recalculateEfficiencyGeneral(intComponentToModify, objShip);
}
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, intComponentToModify, fltCurrentArmorHitpoints);
// no efficiecny mod since curernt hp arent used
}
}
if((fltGeneralEfficiency != 0) && (fltEnergyEfficiency != 0))
{
if(isEfficiencyModified(intComponentToModify, objShip))
{
setEfficiencyModifier(intComponentToModify, objShip, 1.0f, 1.0f);
}
setEfficiencyModifier(intComponentToModify, objShip, fltGeneralEfficiency, fltEnergyEfficiency);
}
if(fltFrontShieldRatio > 0)
{
// we reorganize our shields
float fltShieldTotal = getShipShieldHitpointsFrontMaximum(objShip) + getShipShieldHitpointsBackMaximum(objShip);
float fltFrontMax = (fltShieldTotal / 2) * fltFrontShieldRatio;
float fltBackMax = fltShieldTotal - fltFrontMax;
setShipShieldHitpointsFrontMaximum(objShip, fltFrontMax);
setShipShieldHitpointsBackMaximum(objShip, fltBackMax);
}
}
else if(intComponentToModify == ALL_WEAPONS)
{
// do you have any weapons?
for(int intI = 0; intI < WEAPON_SLOTS.length; intI++)
{
if(isShipSlotInstalled(objShip, WEAPON_SLOTS[intI]))
{
if(fltDamageToComponent > 0)
{
float fltCurrentHitpoints = getShipComponentHitpointsCurrent(objShip, WEAPON_SLOTS[intI]);
float fltCurrentArmorHitpoints = getShipComponentArmorHitpointsCurrent(objShip, WEAPON_SLOTS[intI]);
fltCurrentArmorHitpoints = fltCurrentArmorHitpoints - fltDamageToComponent;
if(fltCurrentArmorHitpoints < 0)
{
float fltRemainingDamage = Math.abs(fltCurrentArmorHitpoints);
fltCurrentHitpoints = fltCurrentHitpoints - fltRemainingDamage;
if(fltCurrentHitpoints < 1)
{
return;
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, WEAPON_SLOTS[intI], 0);
setShipComponentHitpointsCurrent(objShip, WEAPON_SLOTS[intI], fltCurrentHitpoints);
recalculateEfficiencyGeneral(WEAPON_SLOTS[intI], objShip);
}
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, WEAPON_SLOTS[intI], fltCurrentArmorHitpoints);
// no efficiecny mod since curernt hp arent used
}
}
if((fltGeneralEfficiency != 0) && (fltEnergyEfficiency != 0))
{
if(isEfficiencyModified(WEAPON_SLOTS[intI], objShip))
{
setEfficiencyModifier(WEAPON_SLOTS[intI], objShip, 1.0f, 1.0f);
}
setEfficiencyModifier(WEAPON_SLOTS[intI], objShip, fltGeneralEfficiency, fltEnergyEfficiency);
}
}
}
}
if(fltCapacitorReinforcePercentage != 0)
{
if(!reinforceShieldsFromCapacitor(objShip, fltCapacitorReinforcePercentage))
{
return;
}
}
if(fltFrontToBackShieldReinforcePercentage != 0)
{
if(!transferFrontShieldToBack(objShip, fltFrontToBackShieldReinforcePercentage))
{
return;
}
}
if(fltBackToFrontShieldReinforcePercentage != 0)
{
if(!transferBackShieldToFront(objShip, fltBackToFrontShieldReinforcePercentage))
{
return;
}
}
}
void performDroidCommands(obj_id objPlayer, string strCommand)
{
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - ENTERED FUNCTION - objplayer passed was: "+objPlayer+" and command was "+strCommand);
//obj_id objDroid = getDroid(something) commented out because we lack the infrastructure
obj_id objShip = space_transition.getContainingShip(objPlayer);
if(!isIdValid(objShip))
{
// ERROR CODE< NO SHIP
debugServerConsoleMsg(null, "SPACE_COMBAT.performDroidCommands - FAILED TO GET SHIP OBJID through getContainingShip(objPlayer) method");
return;
}
if(doDroidPreCheck(objPlayer, objShip, strCommand))
{
dictionary dctCommandInfo = dataTableGetRow("datatables/space_combat/droid_commands.iff", strCommand);
if(dctCommandInfo == null)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.performDroidCommands - FAILED TO GET COMMAND INFO DICTIONARY. STRING NOT FOUND WAS:" + strCommand);
return;
}
string strClientEffect = dctCommandInfo.getString("strClientEffect");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: strClientEffect is: "+strClientEffect);
string strStringId = dctCommandInfo.getString("strStringId");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: strStringId is: "+strStringId);
int intComponentToModify = dctCommandInfo.getInt("intComponentToModify");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: intComponentToModify is: "+intComponentToModify);
float fltEnergyEfficiency = dctCommandInfo.getFloat("fltEnergyEfficiency");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltEnergyEfficiency is: "+fltEnergyEfficiency);
float fltGeneralEfficiency = dctCommandInfo.getFloat("fltGeneralEfficiency");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltGeneralEfficiency is: "+fltGeneralEfficiency);
float fltRepairMin = dctCommandInfo.getFloat("fltRepairMin");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltRepairMin is: "+fltRepairMin);
float fltRepairMax = dctCommandInfo.getFloat("fltRepairMax");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltRepairMax is: "+fltRepairMax);
// validate the component
float fltBaseDelay = dctCommandInfo.getFloat("fltBaseDelay");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltBaseDelay is: "+fltRepairMax);
float fltRepairKitConsumed = dctCommandInfo.getFloat("fltRepairKitConsumed");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltRepairKitConsumed is: "+fltRepairKitConsumed);
float fltCountermeasureCapacitorCost = dctCommandInfo.getFloat("fltCountermeasureCapacitorCost");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltCountermeasureCapacitorCost is: "+fltCountermeasureCapacitorCost);
float fltCountermeasureShieldCost = dctCommandInfo.getFloat("fltCountermeasureShieldCost");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltCountermeasureShieldCost is: "+fltCountermeasureShieldCost);
float fltFrontToBackShieldReinforcePercentage = dctCommandInfo.getFloat("fltFrontToBackShieldReinforcePercentage");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltFrontToBackShieldReinforcePercentage is: "+fltFrontToBackShieldReinforcePercentage);
float fltBackToFrontShieldReinforcePercentage = dctCommandInfo.getFloat("fltBackToFrontShieldReinforcePercentage");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltBackToFrontShieldReinforcePercentage is: "+fltBackToFrontShieldReinforcePercentage);
float fltCapacitorReinforcePercentage = dctCommandInfo.getFloat("fltCapacitorReinforcePercentage");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltCapacitorReinforcePercentage is: "+fltCapacitorReinforcePercentage);
float fltMissileSavingThrow = dctCommandInfo.getFloat("fltMissileSavingThrow");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltMissileSavingThrow is: "+fltMissileSavingThrow);
string strMessageHandlerOnPlayer = dctCommandInfo.getString("strMessageHandlerOnPlayer");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: strMessageHandlerOnPlayer is: "+strMessageHandlerOnPlayer);
float fltDamageToComponent = dctCommandInfo.getFloat("fltDamageToComponent");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltDamageToComponent is: "+fltDamageToComponent);
float fltFrontShieldRatio = dctCommandInfo.getFloat("fltFrontShieldRatio");
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands - dctCommandInfo data: fltDamageToComponent is: "+fltFrontShieldRatio);
//debugServerConsoleMsg( null, "SPACE_COMBAT.performDroidCommands");
// do damage checks
// Delay stuff
float fltComponentDelay = getShipDroidInterfaceCommandSpeed(objShip);
if(fltComponentDelay < 1)
{
fltComponentDelay = 1.0f;
}
if((intComponentToModify != NONE) && (intComponentToModify != ALL_WEAPONS))
{
if(!isShipSlotInstalled(objShip, intComponentToModify))
{
string_id strSpam = new string_id("space/space_interaction", "droid_component_not_installed");
sendSystemMessage(objPlayer, strSpam);
return;
}
if(fltDamageToComponent > 0)
{
float fltCurrentHitpoints = getShipComponentHitpointsCurrent(objShip, intComponentToModify);
float fltCurrentArmorHitpoints = getShipComponentArmorHitpointsCurrent(objShip, intComponentToModify);
fltCurrentArmorHitpoints = fltCurrentArmorHitpoints - fltDamageToComponent;
if(fltCurrentArmorHitpoints < 0)
{
float fltRemainingDamage = Math.abs(fltCurrentArmorHitpoints);
fltCurrentHitpoints = fltCurrentHitpoints - fltRemainingDamage;
if(fltCurrentHitpoints < 0)
{
string_id strSpam = new string_id("space/space_interaction", "droid_component_too_damaged");
string_id strComponent = new string_id("space/space_interaction", space_crafting.getShipComponentStringType(intComponentToModify));
prose_package proseTest = prose.getPackage(strSpam, strComponent);
return;
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, intComponentToModify, 0);
setShipComponentHitpointsCurrent(objShip, intComponentToModify, fltCurrentHitpoints);
recalculateEfficiencyGeneral(intComponentToModify, objShip);
}
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, intComponentToModify, fltCurrentArmorHitpoints);
// no efficiecny mod since curernt hp arent used
}
}
if((fltGeneralEfficiency != 0) && (fltEnergyEfficiency != 0))
{
if(isEfficiencyModified(intComponentToModify, objShip))
{
setEfficiencyModifier(intComponentToModify, objShip, 1.0f, 1.0f);
//string_id strSpam = new string_id("space/space_interaction", "component_already_modified");
//sendSystemMessage(objPlayer, strSpam);
//return;
}
setEfficiencyModifier(intComponentToModify, objShip, fltGeneralEfficiency, fltEnergyEfficiency);
}
if(fltFrontShieldRatio > 0)
{
// we reorganize our shields
float fltShieldTotal = getShipShieldHitpointsFrontMaximum(objShip) + getShipShieldHitpointsBackMaximum(objShip);
float fltFrontMax = (fltShieldTotal / 2) * fltFrontShieldRatio;
float fltBackMax = fltShieldTotal - fltFrontMax;
setShipShieldHitpointsFrontMaximum(objShip, fltFrontMax);
setShipShieldHitpointsBackMaximum(objShip, fltBackMax);
}
}
else if(intComponentToModify == ALL_WEAPONS)
{
// do you have any weapons?
for(int intI = 0; intI < WEAPON_SLOTS.length; intI++)
{
if(isShipSlotInstalled(objShip, WEAPON_SLOTS[intI]))
{
if(fltDamageToComponent > 0)
{
float fltCurrentHitpoints = getShipComponentHitpointsCurrent(objShip, WEAPON_SLOTS[intI]);
float fltCurrentArmorHitpoints = getShipComponentArmorHitpointsCurrent(objShip, WEAPON_SLOTS[intI]);
fltCurrentArmorHitpoints = fltCurrentArmorHitpoints - fltDamageToComponent;
if(fltCurrentArmorHitpoints < 0)
{
float fltRemainingDamage = Math.abs(fltCurrentArmorHitpoints);
fltCurrentHitpoints = fltCurrentHitpoints - fltRemainingDamage;
if(fltCurrentHitpoints < 1)
{
string_id strSpam = new string_id("space/space_interaction", "droid_command_weapons_too_damaged");
space_utils.sendSystemMessageShip(objShip, strSpam, true, true, true, true);
return;
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, WEAPON_SLOTS[intI], 0);
setShipComponentHitpointsCurrent(objShip, WEAPON_SLOTS[intI], fltCurrentHitpoints);
recalculateEfficiencyGeneral(WEAPON_SLOTS[intI], objShip);
}
}
else
{
setShipComponentArmorHitpointsCurrent(objShip, WEAPON_SLOTS[intI], fltCurrentArmorHitpoints);
// no efficiecny mod since curernt hp arent used
}
}
if((fltGeneralEfficiency != 0) && (fltEnergyEfficiency != 0))
{
if(isEfficiencyModified(WEAPON_SLOTS[intI], objShip))
{
setEfficiencyModifier(WEAPON_SLOTS[intI], objShip, 1.0f, 1.0f);
}
setEfficiencyModifier(WEAPON_SLOTS[intI], objShip, fltGeneralEfficiency, fltEnergyEfficiency);
}
}
}
}
if(fltCapacitorReinforcePercentage != 0)
{
if(!reinforceShieldsFromCapacitor(objShip, fltCapacitorReinforcePercentage))
{
string_id strSpam = new string_id("space/space_interaction", "no_capacitor_energy");
sendSystemMessage(objPlayer, strSpam);
return;
}
}
if(fltFrontToBackShieldReinforcePercentage != 0)
{
if(!transferFrontShieldToBack(objShip, fltFrontToBackShieldReinforcePercentage))
{
// you shouldnt hit this unless someone fucked something up.
string_id strSpam = new string_id("space/space_interaction", "no_front_shield_energy");
sendSystemMessage(objPlayer, strSpam);
return;
}
}
if(fltBackToFrontShieldReinforcePercentage != 0)
{
if(!transferBackShieldToFront(objShip, fltBackToFrontShieldReinforcePercentage))
{
// you shouldnt hit this unless someone fucked something up.
string_id strSpam = new string_id("space/space_interaction", "no_back_shield_energy");
sendSystemMessage(objPlayer, strSpam);
return;
}
}
if(strMessageHandlerOnPlayer != "")
{
space_utils.notifyObject(objPlayer, strMessageHandlerOnPlayer, dctCommandInfo);
}
if(fltBaseDelay > 0)
{
int intTime = getGameTime();
float fltFullDelay = fltComponentDelay * fltBaseDelay;
intTime = intTime + (int) fltFullDelay;
utils.setLocalVar(objShip, "intDroidTimestamp", intTime);
string_id strSpam = new string_id("space/space_interaction", "droid_delay_ready");
space_utils.sendDelayedSystemMessage(objPlayer, strSpam, fltFullDelay);
}
//After doing a droid command, see about having the droid vocalize a low-level.
if(strStringId != "")
{
string_id strSpam = new string_id("space/droid_commands", strStringId);
prose_package pp = prose.getPackage(strSpam);
flightDroidVocalize(objShip, 2, pp);
}
else
{
flightDroidVocalize(objShip, 2);
}
}
}
boolean doDroidPreCheck(obj_id objPlayer, obj_id objShip, string strCommand)
{
// do you have a droid interface
// is it disabled
// do you have a control device
int intCurrentTime = getGameTime();
int intLastTime = utils.getIntLocalVar(objShip, "intDroidTimestamp");
if(intCurrentTime < intLastTime)
{
string_id strSpam = new string_id("space/space_interaction", "droid_command_delay");
prose_package pp = prose.getPackage(strSpam, intLastTime - intCurrentTime);
sendSystemMessageProse(objPlayer, pp);
return false;
}
if(!isShipSlotInstalled(objShip, ship_chassis_slot_type.SCST_droid_interface))
{
// no droid interface, so you cant do anything.
string_id strSpam = new string_id("space/space_interaction", "droid_command_fail_no_interface");
sendSystemMessage(objPlayer, strSpam);
return false;
}
if(isShipComponentDisabled(objShip, ship_chassis_slot_type.SCST_droid_interface))
{
// disabled interface, so no
sendSystemMessage(objPlayer, SID_DISABLED);
string_id strSpam = new string_id("space/space_interaction", "droid_command_fail_interface_disabled");
sendSystemMessage(objPlayer, strSpam);
//./././././././././././././././././././././././/../././././././../.
return false;
}
obj_id objControlDevice = getDroidControlDeviceForShip(objShip);
if(!isIdValid(objControlDevice))
{
string_id strSpam = new string_id("space/space_interaction", "droid_command_fail_no_droid");
sendSystemMessage(objPlayer, strSpam);
return false;
}
if(!droidHasAbility(objControlDevice, strCommand))
{
string_id strSpam = new string_id("space/space_interaction", "droid_command_fail_no_command");
sendSystemMessage(objPlayer, strSpam);
return false;
}
return true;
}
boolean droidHasAbility(obj_id objControlDevice, string strCommand)
{
//Look in the droid datapad slot.
obj_id objDataPad = utils.getDatapad(objControlDevice);
if(!isIdValid(objDataPad))
{
////////LOG("space", "No datapad defined for "+objControlDevice);
return false;
}
obj_id[] objContents = utils.getContents(objDataPad);
boolean retval = false;
////////LOG("space", "contents length is "+objContents.length);
for(int intI = 0; intI < objContents.length; intI++)
{
if(hasObjVar(objContents[intI], "strDroidCommand"))
{
////////LOG("space", "hasObjVar");
string strTest = getStringObjVar(objContents[intI], "strDroidCommand");
if(strTest == strCommand)
{
retval = true;
}
}
}
return retval;
}
float getCommandEfficacy(obj_id objDroid, string strCategory, float fltEfficacy)
{
// returns droid effeceinecyies
// per category, retirns efficacy of a given categoryof commands
// categories.. so weponas, shield
// weapons
// sheidls
// enerrgy transferrence
// engines
// repair
// countermeasures
return 1.0f;
}
void registerDamageDoneToShip(obj_id objAttacker, obj_id objDefender, float fltDamage)
{
if(fltDamage == 0)
{
return; // no need to do anything
}
////////LOG("space", "registering "+objAttacker+" doing "+fltDamage+" to "+objDefender);
// we check if it's a non-player controlled ship
if(!space_utils.isPlayerControlledShip(objAttacker))
{
// we dont track if attacker is non-player
if(hasObjVar(objAttacker, "commanderPlayer"))
{
obj_id objCommander = getObjIdObjVar(objAttacker, "commanderPlayer");
if(isIdValid(objCommander) && (objCommander.isLoaded()))
{
obj_id objShip = space_transition.getContainingShip(objCommander);
if(isIdValid(objShip))
{
objAttacker = objShip;
}
else
{
return;
}
}
else
{
return;
}
}
else
{
return;
}
}
if(space_utils.isPlayerControlledShip(objDefender))
{
// we dont track on player ships
return;
}
resizeable obj_id[] objAttackers = new obj_id[0];
resizeable float[] fltDamageTracked = new obj_id[0];
resizeable float[] fltGroupDamage = new float[0];
if(utils.hasLocalVar(objDefender, "combat.objAttackers"))
{
//LOG("space", "checking our scriptvars which we found");
objAttackers = utils.getResizeableObjIdArrayLocalVar(objDefender, "combat.objAttackers");
fltDamageTracked = utils.getResizeableFloatArrayLocalVar(objDefender, "combat.fltDamageTracked");
}
else
{
//LOG("space", "FOUND NOTHING");
}
int intIndex = -1;
obj_id objGroup = getGroupObject(objAttacker);
if(!isIdValid(objGroup))
{
intIndex = utils.getElementPositionInArray(objAttackers, objAttacker); // are we trackign this attacker already?
//LOG("space", "objAttackers length is "+objAttackers);
//LOG("space", "MNo group, index is "+intIndex);
}
else
{
intIndex = utils.getElementPositionInArray(objAttackers, objGroup); // are we trackign this attacker already?
//LOG("space", "group, index is "+intIndex);
}
if(intIndex > -1)
{
// now we add our damage to the tracking value
fltDamageTracked[intIndex] = fltDamageTracked[intIndex] + fltDamage; // DO NOT MOVE THIS SINCE WE REUSE INTINDEX BELOW
if(isIdValid(objGroup))
{
// the attacker is the group object. // let's get our array
resizeable obj_id[] objGroupMembers = utils.getResizeableObjIdArrayLocalVar(objDefender, "combat.groups." + objGroup);
intIndex = utils.getElementPositionInArray(objGroupMembers, objAttacker);
fltGroupDamage = utils.getResizeableFloatArrayLocalVar(objDefender, "combat.groups." + objGroup + ".fltDamage");
if(intIndex < 0)
{
// not tracking shlomo the ownder chicken
objGroupMembers = utils.addElement(objGroupMembers, objAttacker);
fltGroupDamage = utils.addElement(fltGroupDamage, fltDamage);
utils.setLocalVar(objDefender, "combat.groups." + objGroup, objGroupMembers); // we add this guy to our array.. they participated
utils.setLocalVar(objDefender, "combat.groups." + objGroup + ".fltDamage", fltGroupDamage);
}
else
{
fltGroupDamage[intIndex] = fltGroupDamage[intIndex] + fltDamage; // we track individual group members damage
utils.setLocalVar(objDefender, "combat.groups." + objGroup + ".fltDamage", fltGroupDamage);
}
}
}
else
{
if(isIdValid(objGroup))
{
// it's a group, but we're not tracking it.
objAttackers = utils.addElement(objAttackers, objGroup);
fltDamageTracked = utils.addElement(fltDamageTracked, fltDamage);
resizeable obj_id[] objGroupMembers = new obj_id[0];
objGroupMembers = utils.addElement(objGroupMembers, objAttacker); // they participated
fltGroupDamage = utils.addElement(fltGroupDamage, fltDamage);
utils.setLocalVar(objDefender, "combat.groups." + objGroup, objGroupMembers);
utils.setLocalVar(objDefender, "combat.groups." + objGroup + ".fltDamage", fltGroupDamage);
}
objAttackers = utils.addElement(objAttackers, objAttacker);
fltDamageTracked = utils.addElement(fltDamageTracked, fltDamage);
}
utils.setLocalVar(objDefender, "combat.objAttackers", objAttackers);
utils.setLocalVar(objDefender, "combat.fltDamageTracked", fltDamageTracked);
return;
}
void doFactionPointGrant(obj_id objPlayer, int intImperialFactionPoints, int intRebelFactionPoints)
{
if(intImperialFactionPoints != 0)
{
factions.addFactionStanding(objPlayer, factions.FACTION_IMPERIAL, (float) intImperialFactionPoints);
}
if(intRebelFactionPoints != 0)
{
factions.addFactionStanding(objPlayer, factions.FACTION_REBEL, (float) intRebelFactionPoints);
}
return;
}
void grantRewardsAndCreditForKills(obj_id objDefender)
{
//LOG("space", "getting kill percentages");
dictionary dctParams = getKillPercentages(objDefender);
if(dctParams == null)
{
//LOG("space", "NULL");
return; //??????
}
obj_id[] objAttackers = dctParams.getObjIdArray("objAttackers");
if(objAttackers == null)
{
return;
}
obj_id objWinner = dctParams.getObjId("objWinner");
if(!isIdValid(objWinner))
{
return;
}
float[] fltPercentages = dctParams.getFloatArray("fltPercentages");
obj_id[] objWinningMembers = dctParams.getObjIdArray("objWinningMembers"); // if this is null, no groups involves
float[] fltWinningMemberDamage = dctParams.getFloatArray("fltWinningMemberDamage");
// percentages is how much damage they did
// obj_id attackers is who did it
// winner is the person who got the most damage.
// winner could be a group! that is important
// winning members i sthe group members who particiapted.. they all get credit and stuff
// we grant "credit" to everyone over the minimum
// then we make our loot
// and grant looting rights
//////////LOG("space", "length of array returned is "+objAttackers.length);
int intXP = getIntObjVar(objDefender, "xp.intXP");
for(int intI = 0; intI < objAttackers.length; intI++)
{
if((objAttackers[intI].isLoaded() && (objAttackers[intI].isAuthoritative())))
{
//LOG("space", "objAttackers["+intI+"] is "+objAttackers[intI]);
if(fltPercentages[intI] > MINIMUM_DAMAGE_THRESHOLD)
{
// YOU GET CREDIT!
//LOG("space", "nofitying "+objAttackers[intI]);
notifyAttacker(objAttackers[intI], objDefender, fltPercentages[intI]);
resizeable obj_id[] objPlayers = space_transition.getContainedPlayers(objAttackers[intI], null);
if((objPlayers != null) && (objPlayers.length > 0))
{
// you get some xp too
int intAmount = intXP;
float fltTest = (float) intAmount; // casting so i dont screw up
//fltTest = fltTest * fltPercentages[intI]; everyone gets a full share now
fltTest = fltTest / objPlayers.length;
intAmount = (int) fltTest;
//LOG("space", "granting "+intAmount+" of xp");
string defenderType = getStringObjVar(objDefender, "ship.shipName");
//check to see if this updates a collection
string[] slotNames = getAllCollectionSlotsInCategory("kill_" + defenderType);
// FACTION STUFF
int intImperialFactionPoints = 0;
int intRebelFactionPoints = 0;
if((pvpGetType(objAttackers[intI]) == PVPTYPE_DECLARED))
{
intImperialFactionPoints = utils.getIntLocalVar(objDefender, "intImperialFactionPoints");
intRebelFactionPoints = utils.getIntLocalVar(objDefender, "intRebelFactionPoints");
fltTest = (float) intImperialFactionPoints;
fltTest = fltTest / objPlayers.length;
intImperialFactionPoints = (int) fltTest;
fltTest = (float) intRebelFactionPoints;
fltTest = fltTest / objPlayers.length;
intRebelFactionPoints = (int) fltTest;
}
for(int intJ = 0; intJ < objPlayers.length; intJ++)
{
collection.spaceGetCreditForKills(objPlayers[intJ], slotNames);
string tier = getPlayerTierString(objPlayers[intJ]);
if(utils.getIntLocalVar(objDefender, "intRebelFactionPoints") > 0 && factions.isRebel(objPlayers[intJ]))
{
int credit = 0;
if(isCapShip(objDefender))
credit = 30;
else
credit = gcw.getSpaceKillCredit(space_flags.getPilotTier(objPlayers[intJ]), getShipDifficulty(objDefender));
string information = getName(objDefender);
gcw.grantModifiedGcwPoints(objPlayers[intJ], credit, gcw.GCW_POINT_TYPE_SPACE_PVE, information);
}
if(utils.getIntLocalVar(objDefender, "intImperialFactionPoints") > 0 && factions.isImperial(objPlayers[intJ]))
{
int credit = 0;
if(isCapShip(objDefender))
credit = 30;
else
credit = gcw.getSpaceKillCredit(space_flags.getPilotTier(objPlayers[intJ]), getShipDifficulty(objDefender));
string information = getName(objDefender);
gcw.grantModifiedGcwPoints(objPlayers[intJ], credit, gcw.GCW_POINT_TYPE_SPACE_PVE, information);
}
string disableGroundXp = getConfigSetting("GameServer", "disableGroundXpInSpace");
if(disableGroundXp == null || disableGroundXp.equals("false") || disableGroundXp.equals("0"))
{
if(!utils.isProfession(objPlayers[intJ], utils.TRADER) && !utils.isProfession(objPlayers[intJ], utils.ENTERTAINER))
{
int combatLevel = getLevel(objPlayers[intJ]);
if(combatLevel < 90) //don't need a min level check due to profession check above
{
float fltGroundXp = intAmount * GROUND_XP_PERCENT;
int intGroundXp = (int) fltGroundXp;
xp.grant(objPlayers[intJ], "combat_general", intGroundXp);
}
}
}
doFactionPointGrant(objPlayers[intJ], intImperialFactionPoints, intRebelFactionPoints);
if(hasSkill(objPlayers[intJ], "pilot_rebel_navy_master"))
{
xp.grant(objPlayers[intJ], xp.SPACE_PRESTIGE_REBEL, intAmount, true);
CustomerServiceLog("space_xp", "SPACE_PRESTIGE_REBEL|V1|" + tier + "|TIME:" + getGameTime() + "|PLAYER:" + objPlayers[intJ] + "|PLAYER_SHIP:" + getPilotedShip(objPlayers[intJ]) + "|DEFENDER:" + objDefender + "|DEFENDER_TYPE:" + defenderType + "|AMT:" + intAmount);
}
else if(hasSkill(objPlayers[intJ], "pilot_imperial_navy_master"))
{
xp.grant(objPlayers[intJ], xp.SPACE_PRESTIGE_IMPERIAL, intAmount, true);
CustomerServiceLog("space_xp", "SPACE_PRESTIGE_IMPERIAL|V1|" + tier + "|TIME:" + getGameTime() + "|PLAYER:" + objPlayers[intJ] + "|PLAYER_SHIP:" + getPilotedShip(objPlayers[intJ]) + "|DEFENDER:" + objDefender + "|DEFENDER_TYPE:" + defenderType + "|AMT:" + intAmount);
}
else if(hasSkill(objPlayers[intJ], "pilot_neutral_master"))
{
xp.grant(objPlayers[intJ], xp.SPACE_PRESTIGE_PILOT, intAmount, true);
CustomerServiceLog("space_xp", "SPACE_PRESTIGE_PILOT|V1|" + tier + "|TIME:" + getGameTime() + "|PLAYER:" + objPlayers[intJ] + "|PLAYER_SHIP:" + getPilotedShip(objPlayers[intJ]) + "|DEFENDER:" + objDefender + "|DEFENDER_TYPE:" + defenderType + "|AMT:" + intAmount);
}
else
{
xp.grant(objPlayers[intJ], xp.SPACE_COMBAT_GENERAL, intAmount, true);
CustomerServiceLog("space_xp", "SPACE_COMBAT_GENERAL|V1|" + tier + "|TIME:" + getGameTime() + "|PLAYER:" + objPlayers[intJ] + "|PLAYER_SHIP:" + getPilotedShip(objPlayers[intJ]) + "|DEFENDER:" + objDefender + "|DEFENDER_TYPE:" + defenderType + "|AMT:" + intAmount);
int badgeCount = 0;
//rebel badges:
if(badge.hasBadge(objPlayers[intJ], "pilot_rebel_navy_naboo"))
badgeCount++;
else if(badge.hasBadge(objPlayers[intJ], "pilot_rebel_navy_corellia"))
badgeCount++;
else if(badge.hasBadge(objPlayers[intJ], "pilot_rebel_navy_tatooine"))
badgeCount++;
//imperial badges:
if(badge.hasBadge(objPlayers[intJ], "pilot_imperial_navy_naboo"))
badgeCount++;
else if(badge.hasBadge(objPlayers[intJ], "pilot_imperial_navy_corellia"))
badgeCount++;
else if(badge.hasBadge(objPlayers[intJ], "pilot_imperial_navy_tatooine"))
badgeCount++;
//privateer badges:
if(badge.hasBadge(objPlayers[intJ], "pilot_neutral_naboo"))
badgeCount++;
else if(badge.hasBadge(objPlayers[intJ], "pilot_neutral_corellia"))
badgeCount++;
else if(badge.hasBadge(objPlayers[intJ], "pilot_neutral_tatooine"))
badgeCount++;
if(badgeCount > 0)
{
int bonus = intAmount * badgeCount;
string_id sid_xp = new string_id(xp.STF_XP_N, xp.SPACE_COMBAT_GENERAL);
xp.grant(objPlayers[intJ], xp.SPACE_COMBAT_GENERAL, bonus, false); //a silent xp grant
CustomerServiceLog("space_xp", "SPACE_COMBAT_GENERAL_BONUS|TIME:" + getGameTime() + "|PLAYER:" + objPlayers[intJ] + "|PLAYER_SHIP:" + getPilotedShip(objPlayers[intJ]) + "|DEFENDER:" + objDefender + "|DEFENDER_TYPE:" + defenderType + "|AMT:" + bonus);
//tell the player they get MASTER BONUS: xp of x type
prose_package pp = prose.getPackage(xp.PROSE_GRANT_XP_BONUS, sid_xp);
if(exists(objPlayers[intJ]) && (objPlayers[intJ].isLoaded()))
{
sendSystemMessageProse(objPlayers[intJ], pp);
}
}
} //end else you are getting space_combat_general xp
} //end foreach player aboard the ship
} //endif damage threshold > minimum
} //end foreach player piloting an attacking ship
//LOG("space", "WINNER!");
}
}
if(objWinningMembers != null)
{
int intRoll = rand(0, objWinningMembers.length - 1);
// winner is actually a group object. we need to recalculate who the winner actually is
// choose random winner
objWinner = objWinningMembers[rand(0, objWinningMembers.length - 1)];
}
if((objWinner.isLoaded() && (objWinner.isAuthoritative())))
{
createLoot(objDefender, objWinner);
CustomerServiceLog("space_loot", "Creating Loot from " + objDefender + " in " + getLocation(objDefender) + " for " + objWinner);
if(space_battlefield.isInBattlefield(objWinner))
{
CustomerServiceLog("battlefield", "Creating Loot from " + objDefender + " in " + getLocation(objDefender) + " for " + objWinner);
}
}
return;
}
string getPlayerTierString(obj_id player)
{
if(space_flags.isInTierOne(player))
{
return "TIER1";
}
else if(space_flags.isInTierTwo(player))
{
return "TIER2";
}
else if(space_flags.isInTierThree(player))
{
return "TIER3";
}
else if(space_flags.isInTierFour(player))
{
return "TIER4";
}
else
{
return "MASTER";
}
}
void sendCreditNotification(obj_id objShip, int intCredits)
{
resizeable obj_id[] objPlayers = space_transition.getContainedPlayers(objShip);
//LOG("space", "senidng notificaton for interior");
if(space_utils.isShipWithInterior(objShip))
{
// send the "group/pob ship notification"
// it's a general "The <shipName> has looted a credit chip worth <X>"
obj_id objGroup = group.getGroupObject(objPlayers[0]);
if(isIdValid(objGroup))
{
obj_id[] objGroupMembers = space_utils.getSpaceGroupMemberIds(objGroup);
if(objGroupMembers != null)
{
string_id strSpam = new string_id("space/space_loot", "looted_credits");
//prose_package proseTest = prose.getPackage(strSpam, getEncodedName(objShip), intCredits);
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTT(proseTest, getEncodedName(objShip));
proseTest = prose.setDI(proseTest, intCredits);
for(int intI = 0; intI < objGroupMembers.length; intI++)
{
if(exists(objGroupMembers[intI]))
{
sendSystemMessageProse(objGroupMembers[intI], proseTest);
}
}
}
}
else
{
string_id strSpam = new string_id("space/space_loot", "looted_credits_you");
//prose_package proseTest = prose.getPackage(strSpam, objShip, intCredits);
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setDI(proseTest, intCredits);
sendSystemMessageProse(objPlayers[0], proseTest);
}
}
else
{
obj_id objGroup = group.getGroupObject(objPlayers[0]);
if(isIdValid(objGroup))
{
// send group notification about the pilot
obj_id objPilot = getPilotId(objShip);
if(!isIdValid(objPilot))
{
// non pob ship with no pilot.. baaad news
return;
}
string_id strSpam = new string_id("space/space_loot", "looted_credits");
// fucking sucksprose_package proseTest = prose.getPackage(strSpam, getEncodedName(objPilot), intCredits);
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTT(proseTest, getEncodedName(objPilot));
proseTest = prose.setDI(proseTest, intCredits);
if(isIdValid(objGroup))
{
obj_id[] objGroupMembers = space_utils.getSpaceGroupMemberIds(objGroup);
if(objGroupMembers != null)
{
for(int intI = 0; intI < objGroupMembers.length; intI++)
{
if(exists(objGroupMembers[intI]))
{
sendSystemMessageProse(objGroupMembers[intI], proseTest);
}
}
}
}
}
else
{
// send solo notification to teh pilot
obj_id objPilot = getPilotId(objShip);
if(!isIdValid(objPilot))
{
// non pob ship with no pilot.. baaad news
return;
}
string_id strSpam = new string_id("space/space_loot", "looted_credits_you");
//prose_package proseTest = prose.getPackage(strSpam, intCredits);
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setDI(proseTest, intCredits);
sendSystemMessageProse(objPilot, proseTest);
}
}
}
void sendItemNotification(obj_id objShip, obj_id objItem)
{
resizeable obj_id[] objPlayers = space_transition.getContainedPlayers(objShip);
if(space_utils.isShipWithInterior(objShip))
{
// send the "group/pob ship notification"
// it's a general "The <shipName> has looted a credit chip worth <X>"
obj_id objGroup = group.getGroupObject(objPlayers[0]);
if(isIdValid(objGroup))
{
string_id strSpam = new string_id("space/space_loot", "looted_item");
//prose_package proseTest = prose.getPackage(strSpam,getEncodedName(objShip), getEncodedName(objItem));
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTT(proseTest, getEncodedName(objShip));
proseTest = prose.setTO(proseTest, getEncodedName(objItem));
obj_id[] objGroupMembers = space_utils.getSpaceGroupMemberIds(objGroup);
if(objGroupMembers != null)
{
for(int intI = 0; intI < objGroupMembers.length; intI++)
{
if(exists(objGroupMembers[intI]))
{
sendSystemMessageProse(objGroupMembers[intI], proseTest);
}
}
}
}
else
{
string_id strSpam = new string_id("space/space_loot", "looted_item_you");
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTO(proseTest, getEncodedName(objItem));
sendSystemMessageProse(objPlayers[0], proseTest);
}
}
else
{
obj_id objGroup = group.getGroupObject(objPlayers[0]);
if(isIdValid(objGroup))
{
// send group notification about the pilot
obj_id objPilot = getPilotId(objShip);
if(!isIdValid(objPilot))
{
// non pob ship with no pilot.. baaad news
return;
}
string_id strSpam = new string_id("space/space_loot", "looted_item");
//prose_package proseTest = prose.getPackage(strSpam, getName(objPilot), getEncodedName(objItem));
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTT(proseTest, getEncodedName(objPilot));
proseTest = prose.setTO(proseTest, getEncodedName(objItem));
if(isIdValid(objGroup))
{
obj_id[] objGroupMembers = space_utils.getSpaceGroupMemberIds(objGroup);
if(objGroupMembers != null)
{
for(int intI = 0; intI < objGroupMembers.length; intI++)
{
if(exists(objGroupMembers[intI]))
{
sendSystemMessageProse(objGroupMembers[intI], proseTest);
}
}
}
}
}
else
{
// send solo notification to teh pilot
obj_id objPilot = getPilotId(objShip);
if(!isIdValid(objPilot))
{
//LOG("space", "no pilot!");
// non pob ship with no pilot.. baaad news
return;
}
string_id strSpam = new string_id("space/space_loot", "looted_item_you");
//prose_package proseTest = prose.getPackage(strSpam, getEncodedName(objItem));
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTO(proseTest, getEncodedName(objItem));
sendSystemMessageProse(objPilot, proseTest);
}
}
}
void createLoot(obj_id objDefender, obj_id objAttacker)
{
const string LOOT_TABLE = "datatables/space_loot/loot_items.iff";
const string LOOKUP_TABLE = "datatables/space_loot/loot_lookup.iff";
string strContainer = "object/tangible/container/drum/warren_drum_loot.iff";
obj_id objContainer = null;
obj_id objPilot = getPilotId(objAttacker);
if(space_utils.isShipWithInterior(objAttacker))
{
// make loot in the loot box
//LOG("space", objAttacker+" has an interior");
objContainer = getObjIdObjVar(objAttacker, "objLootBox");
}
else
{
// make the loot somewhere else
//LOG("space", "No interior");
if(!isIdValid(objPilot))
{
//LOG("space", "No pilot in this one");
return;
}
objContainer = utils.getInventoryContainer(objPilot);
//LOG("space", "Using container "+objContainer+"from "+objPilot);
}
if(!isIdValid(objContainer))
{
//LOG("space", "null loot container");
return;
}
if(isIdValid(objPilot))
{
// TCG Object Generation
obj_id pilotInv = utils.getInventoryContainer(objPilot);
boolean canDrop = scheduled_drop.canDropCard(scheduled_drop.SYSTEM_COMBAT_SPACE);
boolean hasDelay = scheduled_drop.hasCardDelay(objPilot, scheduled_drop.SYSTEM_COMBAT_SPACE);
if(isGod(objPilot) && hasObjVar(objPilot, "qa_tcg_always_drop"))
{
canDrop = true;
hasDelay = false;
}
if(isIdValid(pilotInv) && canDrop && !hasDelay && isPlayerActive(objPilot))
{
obj_id card = scheduled_drop.dropCard(scheduled_drop.SYSTEM_COMBAT_SPACE, pilotInv);
if(isIdValid(card))
{
string [] cardNameList = split(getName(card), ':');
if(cardNameList.length > 1)
{
string_id cardName = new string_id(cardNameList[0], cardNameList[1]);
string name = getString(cardName);
prose_package pp = new prose_package();
pp = prose.setStringId(pp, new string_id("spam", "tcg_space_loot"));
pp = prose.setTU(pp, name);
sendSystemMessageProse(objPilot, pp);
}
}
}
else
{
if(isGod(objPilot) && hasObjVar(objPilot, "qa_tcg"))
{
sendSystemMessageTestingOnly(objPilot, "QA TCG SPACE NOT DROPPED. Random chance passed? " + canDrop + " Has Card Delay? " + hasDelay);
}
}
utils.setScriptVar(objPilot, scheduled_drop.PLAYER_SCRIPTVAR_DROP_TIME, getGameTime());
}
//Reward Credits
int intCredits = getIntObjVar(objDefender, "loot.intCredits");
if(intCredits > 0)
{
obj_id creditChip = space_create.makeCreditChip(objContainer, intCredits);
if(isIdValid(creditChip))
{
CustomerServiceLog("space_loot", "Made credit chip worth " + intCredits + " in container " + objContainer + " owned by " + objAttacker, getOwner(objAttacker));
sendCreditNotification(objAttacker, intCredits);
}
else
{
CustomerServiceLog("space_loot", "Failed to make credit chip due to inventory/loot box being full " + intCredits + " in container " + objContainer + " owned by " + objAttacker, getOwner(objAttacker));
string_id strSpam = new string_id("space/space_loot", "no_more_credits");
space_utils.sendSystemMessageShip(objAttacker, strSpam, true, true, true, true);
}
}
if(hasObjVar(objDefender, "collection.collectionLoot") && hasObjVar(objDefender, "collection.rollBaseChance"))
{
//Player rolls for collections
int playerRoll = rand(1, 100);
//Get Base Roll Chance from mob.
int rollBaseChance = getIntObjVar(objDefender, "collection.rollBaseChance");
if( buff.hasBuff(objPilot, "nova_orion_rank6_lucky_salvage") )
{
rollBaseChance = rollBaseChance + NOVA_ORION_BUFF_COLLECTIBLES_BONUS;
}
if(playerRoll <= rollBaseChance)
{
//Get Collection Loot List of Mob
string collectionLoot = getStringObjVar(objDefender, "collection.collectionLoot");
boolean success = getCollectionLoot(objAttacker, objPilot, objContainer, collectionLoot);
if(!success)
{
CustomerServiceLog("CollectionLootChannel: ", "LootFailed: " + objDefender + "(" + objPilot + ")" + " failed to receive dropped space collection item due to a failure in the getCollectionLoot function. Notify development.");
}
}
}
//This gets the number of non-collectible loot the NPC ship is going to drop.
int intNumItems = getIntObjVar(objDefender, "loot.intNumItems");
string strTable = getStringObjVar(objDefender, "loot.strLootTable");
string[] strColumns = dataTableGetStringColumnNoDefaults(LOOKUP_TABLE, strTable);
if(strColumns == null)
{
return;
}
if(isIdValid(objPilot) && (utils.getPlayerProfession(objPilot) == utils.SMUGGLER))
{
smuggler.spaceContrabandDropCheck(objPilot);
}
for(int intI = 0; intI < intNumItems; intI++)
{
// we pick a "table"
// get a column
// pick an item from taht colum
int intRoll = rand(0, strColumns.length - 1);
string[] strItems = dataTableGetStringColumnNoDefaults(LOOT_TABLE, strColumns[intRoll]);
if(strItems == null)
{
return;
}
if((strItems != null) && (strItems.length > 0))
{
int intRoll2 = rand(0, strItems.length - 1);
string itemTemplateName = "";
if(getConfigSetting("GameServer", "enableLevelUpLoot") != null && (rand(1, 10000) == 1))
itemTemplateName = "object/tangible/loot/quest/levelup_lifeday_orb.iff";
else
itemTemplateName = strItems[intRoll2];
if(space_battlefield.isInBattlefield(objAttacker))
{
CustomerServiceLog("battlefield", "%TU Created " + itemTemplateName + " in " + objContainer + " contained by " + objAttacker, getOwner(objAttacker));
}
boolean success = attemptToGrantLootItem(itemTemplateName, objAttacker, objContainer);
if(!success)
break; //we don't want to loop anymore if inventory is full.
}
else
{
//space_utils.sendDebugSpam(objAttacker, "BAD ITEM ENTRY FOR LOOT, VALUE IS "+strColumns[intRoll]);
return;
}
}
//begin Nova Orion Resource creation
if(hasObjVar(objDefender, "loot.novaOrionLoot"))
{
//determine if they have gotten it
int chance = rand(1,100);
if( buff.hasBuff(objPilot, "nova_orion_rank6_lucky_salvage") )
{
chance = chance - NOVA_ORION_BUFF_MIDLITHE_BONUS;
}
if(chance <= NOVA_ORION_RESOURCE_CHANCE)
{
int novaOrionLootModifier = getIntObjVar(objDefender, "loot.novaOrionLoot");
int min = NOVA_ORION_RESOURCE_MIN + novaOrionLootModifier;
int max = NOVA_ORION_RESOURCE_MAX + novaOrionLootModifier;
int count = rand(min, max);
obj_id[] contents = getContents(objContainer);
boolean foundCrystal = false;
if(contents != null && contents.length > 0)
{
for(int i = 0; i < contents.length; ++i)
{
if(static_item.isStaticItem(contents[i]) && getStaticItemName(contents[i]).equals(NOVA_ORION_RESOURCE))
{
int oldCount = getCount(contents[i]);
int newCount = oldCount + count;
setCount(contents[i], newCount);
foundCrystal = true;
break;
}
}
}
if(!foundCrystal)
{
obj_id lootItem = static_item.createNewItemFunction(NOVA_ORION_RESOURCE, objContainer); // create item and place in mob's inventory
setCount(lootItem, count);
}
string_id strSpam = new string_id("space/space_loot", "looted_item_you");
//prose_package proseTest = prose.getPackage(strSpam, getEncodedName(objItem));
prose_package proseTest = new prose_package();
proseTest = prose.setStringId(proseTest, strSpam);
proseTest = prose.setTO(proseTest, utils.packStringId(new string_id(static_item.STATIC_ITEM_NAME, NOVA_ORION_RESOURCE)));
sendSystemMessageProse(objPilot, proseTest);
}
}
return;
}
void grantLootPermission(obj_id objWinner, obj_id objContainer)
{
// grants permission to loot the container
resizeable obj_id[] objWinners = new obj_id[0];
if(hasObjVar(objContainer, "objLooters"))
{
objWinners = getResizeableObjIdArrayObjVar(objContainer, "objLooters");
}
objWinners = utils.addElement(objWinners, objWinner);
setObjVar(objContainer, "objLooters", objWinners);
//////////LOG("space", "granted loot stuff");
return;
}
void notifyAttacker(obj_id objAttacker, obj_id objDefender, float fltPercentage)
{
dictionary dctParams = new dictionary();
dctParams.put("ship", objDefender);
string strShipType = getStringObjVar(objDefender, "ship.shipName");
if(strShipType != null)
{
dctParams.put("strShipType", strShipType);
}
obj_id sourceSpawner = getObjIdObjVar(objDefender, "objParent");
if(isIdValid(sourceSpawner))
{
string spawner_name = getStringObjVar(sourceSpawner, "strSpawnerName");
if(spawner_name != null)
{
dctParams.put("strSpawnerName", spawner_name);
}
}
dctParams.put("fltPercentage", fltPercentage);
space_utils.notifyObject(objAttacker, "targetDestroyed", dctParams);
return;
}
void notifyAttackerDisabled(obj_id objAttacker, obj_id objDefender, dictionary dctParams)
{
dctParams.put("ship", objDefender);
string strShipType = getStringObjVar(objDefender, "ship.shipName");
if(strShipType != null)
{
dctParams.put("strShipType", strShipType);
}
obj_id sourceSpawner = getObjIdObjVar(objDefender, "objParent");
if(isIdValid(sourceSpawner))
{
string spawner_name = getStringObjVar(sourceSpawner, "strSpawnerName");
if(spawner_name != null)
{
dctParams.put("strSpawnerName", spawner_name);
}
}
space_utils.notifyObject(objAttacker, "targetDisabled", dctParams);
return;
}
dictionary getKillPercentages(obj_id objDefender)
{
// returns 2 arrays
// obj_id's
// and floats
// in order?
// NO!, but we'll return the top values
resizeable obj_id[] objAttackers = new obj_id[0];
resizeable float[] fltPercentages = new float[0];
float fltTotalDamage = 0;
dictionary dctParams = new dictionary();
float fltMaxDamage = 0; // how much was the most damage done
int intMaxDamageIndex = 0; // what index are they at?
obj_id[] objTrackedAttackers = utils.getObjIdArrayLocalVar(objDefender, "combat.objAttackers");
////////LOG("space", "length of array is "+objTrackedAttackers.length);
float[] fltTrackedDamage = utils.getFloatArrayLocalVar(objDefender, "combat.fltDamageTracked");
if(fltTrackedDamage != null && objTrackedAttackers != null)
{
for(int intI = 0; intI < fltTrackedDamage.length; intI++)
{
if((objTrackedAttackers[intI].isLoaded() && (objTrackedAttackers[intI].isAuthoritative())))
{
if(fltMaxDamage < fltTrackedDamage[intI])
{
fltMaxDamage = fltTrackedDamage[intI];
intMaxDamageIndex = intI;
}
fltTotalDamage = fltTotalDamage + fltTrackedDamage[intI];
}
}
// now we calculate how much everyone did (including the groups)
dctParams.put("fltTotalDamage", fltTotalDamage);
dctParams.put("fltMaxDamage", fltMaxDamage);
dctParams.put("intMaxDamageIndex", intMaxDamageIndex);
dctParams.put("objWinner", objTrackedAttackers[intMaxDamageIndex]);
if(utils.hasLocalVar(objDefender, "combat.groups." + objTrackedAttackers[intMaxDamageIndex])) // THIS IS A GROUP. We need to return teh array of the defenders
{
dctParams.put("objWinningMembers", utils.getObjIdArrayLocalVar(objDefender, "combat.groups." + objTrackedAttackers[intMaxDamageIndex]));
dctParams.put("fltWinningMemberDamage", utils.getFloatArrayLocalVar(objDefender, "combat.groups." + objTrackedAttackers[intMaxDamageIndex] + "fltDamage"));
}
float fltDamage = 0; // tracker for calcs;
float fltPercentage = 0; // tracker for calcs
for(int intI = 0; intI < objTrackedAttackers.length; intI++)
{
////////LOG("space", "Iterating!");
fltDamage = fltTrackedDamage[intI];
fltPercentage = fltDamage / fltTotalDamage;
// check for groups. if we find that something is a group
// we grant everyone in teh group the same percentage of the stuff
if(utils.hasLocalVar(objDefender, "combat.groups." + objTrackedAttackers[intI]))
{
obj_id[] objGroupMembers = utils.getObjIdArrayLocalVar(objDefender, "combat.groups." + objTrackedAttackers[intI]); // get the list
for(int intJ = 0; intJ < objGroupMembers.length; intJ++)
{
// every group member gets added to our tracked list
////////LOG("space", "adding "+objGroupMembers[intI]+" to your array");
if((objGroupMembers[intJ].isLoaded() && (objGroupMembers[intJ].isAuthoritative())))
{
objAttackers = utils.addElement(objAttackers, objGroupMembers[intJ]);
fltPercentages = utils.addElement(fltPercentages, fltPercentage); // all get same %
}
}
}
else
{
////////LOG("space", "adding "+objTrackedAttackers[intI]+" to your array");
if(objTrackedAttackers[intI].isLoaded() && objTrackedAttackers[intI].isAuthoritative())
{
objAttackers = utils.addElement(objAttackers, objTrackedAttackers[intI]);
fltPercentages = utils.addElement(fltPercentages, fltPercentage);
}
}
}
if(objAttackers.length > 0)
{
dctParams.put("objAttackers", objAttackers);
dctParams.put("fltPercentages", fltPercentages);
}
}
return dctParams;
}
void setEfficiencyModifier(int intSlot, obj_id objShip, float fltGeneralModifier, float fltEnergyModifier)
{
////////LOG("space", "setting effeciencies to General:"+fltGeneralModifier+" and Energy:"+fltEnergyModifier);
if((fltGeneralModifier == 1.0f) && (fltEnergyModifier == 1.0f))
{
clearEfficiencyModifier(intSlot, objShip);
return;
}
else
{
string strName = ship_chassis_slot_type.names[intSlot];
utils.setLocalVar(objShip, strName + "Efficiency", 1);
utils.setLocalVar(objShip, strName + "EfficiencyGeneral", fltGeneralModifier);
utils.setLocalVar(objShip, strName + "EfficiencyEnergy", fltEnergyModifier);
recalculateEfficiency(intSlot, objShip);
}
return;
}
void clearEfficiencyModifier(int intSlot, obj_id objShip)
{
string strName = ship_chassis_slot_type.names[intSlot];
utils.removeLocalVar(objShip, strName + "Efficiency");
utils.removeLocalVar(objShip, strName + "EfficiencyGeneral");
utils.removeLocalVar(objShip, strName + "EfficiencyEnergy");
recalculateEfficiency(intSlot, objShip);
return;
}
boolean isEfficiencyModified(int intSlot, obj_id objShip)
{
string strName = ship_chassis_slot_type.names[intSlot];
if(utils.hasLocalVar(objShip, strName + "Efficiency"))
{
return true;
}
return false;
}
void recalculateEfficiency(int intSlot, obj_id objShip, float fltRawEfficiency)
{
////////LOG("space", "raw effeciency is "+fltRawEfficiency);
if(fltRawEfficiency == 0)
{
return;
}
string strName = ship_chassis_slot_type.names[intSlot];
float fltEnergyModifier = 1.0f;
float fltGeneralModifier = 1.0f;
if(utils.hasLocalVar(objShip, strName + "Efficiency"))
{
fltGeneralModifier = utils.getFloatLocalVar(objShip, strName + "EfficiencyGeneral");
fltEnergyModifier = utils.getFloatLocalVar(objShip, strName + "EfficiencyEnergy");
////////LOG("space", "fltGeneralModifier:"+fltGeneralModifier+" EnergyModifier is "+fltEnergyModifier);
}
float fltFinalGeneralEfficiency = fltGeneralModifier * fltRawEfficiency;
float fltFinalEnergyEfficiency = fltEnergyModifier;
////////LOG("space", "Final GEneral is "+fltFinalGeneralEfficiency+" and Final Energy is "+fltFinalEnergyEfficiency);
setEfficiencies(intSlot, objShip, fltFinalGeneralEfficiency, fltFinalEnergyEfficiency);
}
void recalculateEfficiencyGeneral(int intSlot, obj_id objShip)
{
recalculateEfficiencyGeneral(intSlot, objShip, getRawEfficiency(intSlot, objShip));
}
void recalculateEfficiencyGeneral(int intSlot, obj_id objShip, float fltRawEfficiency)
{
////////LOG("space", "raw effeciency is "+fltRawEfficiency);
if(fltRawEfficiency == 0)
{
return;
}
string strName = ship_chassis_slot_type.names[intSlot];
float fltGeneralModifier = 1.0f;
if(utils.hasLocalVar(objShip, strName + "Efficiency"))
{
fltGeneralModifier = utils.getFloatLocalVar(objShip, strName + "EfficiencyGeneral");
}
float fltFinalGeneralEfficiency = fltGeneralModifier * fltRawEfficiency;
////////LOG("space", "Final GEneral is "+fltFinalGeneralEfficiency+" and Final Energy is "+fltFinalEnergyEfficiency);
setEfficiencyGeneral(intSlot, objShip, fltFinalGeneralEfficiency);
}
void recalculateEfficiency(int intSlot, obj_id objShip)
{
float fltRawEfficiency = getRawEfficiency(intSlot, objShip);
recalculateEfficiency(intSlot, objShip, fltRawEfficiency);
}
void setEfficiencyGeneral(int intSlot, obj_id objShip, float fltGeneralModifier)
{
if(fltGeneralModifier < MINIMUM_EFFICIENCY)
{
fltGeneralModifier = MINIMUM_EFFICIENCY;
}
setShipComponentEfficiencyGeneral(objShip, intSlot, fltGeneralModifier);
return;
}
void setEfficiencies(int intSlot, obj_id objShip, float fltGeneralModifier, float fltEnergyModifier)
{
////////LOG("space", "Passed into setefficiencies GENERAL:"+fltGeneralModifier+" and ENERGY:"+fltEnergyModifier);
if(fltEnergyModifier < MINIMUM_EFFICIENCY)
{
fltEnergyModifier = MINIMUM_EFFICIENCY;
}
if(fltGeneralModifier < MINIMUM_EFFICIENCY)
{
fltGeneralModifier = MINIMUM_EFFICIENCY;
}
////////LOG("space", "Setting Genersal to "+fltGeneralModifier);
////////LOG("space", "Setting Energy to "+fltEnergyModifier);
setShipComponentEfficiencyGeneral(objShip, intSlot, fltGeneralModifier);
setShipComponentEfficiencyEnergy(objShip, intSlot, fltEnergyModifier);
return;
}
void zeroEfficienciesClearPowerups(int intSlot, obj_id objShip)
{
string strName = ship_chassis_slot_type.names[intSlot];
utils.removeLocalVar(objShip, strName + "Efficiency");
utils.removeLocalVar(objShip, strName + "EfficiencyGeneral");
utils.removeLocalVar(objShip, strName + "EfficiencyEnergy");
setEfficiencies(intSlot, objShip, 0.0f, 0.0f);
return;
}
float getRawEfficiency(int intSlot, obj_id objShip)
{
// just the hp compariosn efficiency
boolean boolUpdateComponent = true;
float fltCurrentHitpoints = getShipComponentHitpointsCurrent(objShip, intSlot);
float fltMaximumHitpoints = getShipComponentHitpointsMaximum(objShip, intSlot);
if(fltMaximumHitpoints == 0)
{
if(hasScript(objShip, "space.ship.ship_interior"))
{
dictionary dctParams = new dictionary();
dctParams.put("intSlot", intSlot);
space_utils.notifyObject(objShip, "componentDisabledByDamage", dctParams);
boolUpdateComponent = false; // Don't double update the interior stuff
}
space_utils.setComponentDisabled(objShip, intSlot, true);
return 0;
}
if(fltCurrentHitpoints == 0)
{
if(hasScript(objShip, "space.ship.ship_interior"))
{
dictionary dctParams = new dictionary();
dctParams.put("intSlot", intSlot);
space_utils.notifyObject(objShip, "componentDisabledByDamage", dctParams);
boolUpdateComponent = false; // Don't double update the interior stuff
}
space_utils.setComponentDisabled(objShip, intSlot, true);
return 0;
}
if(boolUpdateComponent)
{
if(hasScript(objShip, "space.ship.ship_interior"))
{
dictionary dctParams = new dictionary();
dctParams.put("intSlot", intSlot);
dctParams.put("fltCurrentHitpoints", fltCurrentHitpoints);
dctParams.put("fltMaximumHitpoints", fltMaximumHitpoints);
space_utils.notifyObject(objShip, "componentEfficiencyChanged", dctParams);
}
}
////////LOG("space", "fltCurrentHitpoints = "+fltCurrentHitpoints+" fltMaximumHitpoints = "+fltMaximumHitpoints);
float fltEfficiency = fltCurrentHitpoints / fltMaximumHitpoints;
return fltEfficiency; // raw effeciency
}
void recalculateEfficiencies(obj_id objComponent)
{
float fltMaximumHitpoints = space_crafting.getComponentMaximumHitpoints(objComponent);
float fltCurrentHitpoints = space_crafting.getComponentCurrentHitpoints(objComponent);
float fltEfficiency = 0;
if(fltCurrentHitpoints > 0)
{
fltEfficiency = fltMaximumHitpoints / fltCurrentHitpoints;
}
else
{
fltEfficiency = 0;
}
setEfficiencies(objComponent, fltEfficiency, fltEfficiency);
}
void setEfficiencies(obj_id objComponent, float fltGeneralModifier, float fltEnergyModifier)
{
////////LOG("space", "Passed into setefficiencies GENERAL:"+fltGeneralModifier+" and ENERGY:"+fltEnergyModifier);
if(fltEnergyModifier < MINIMUM_EFFICIENCY)
{
fltEnergyModifier = MINIMUM_EFFICIENCY;
}
if(fltGeneralModifier < MINIMUM_EFFICIENCY)
{
fltGeneralModifier = MINIMUM_EFFICIENCY;
}
////////LOG("space", "Setting Genersal to "+fltGeneralModifier);
////////LOG("space", "Setting Energy to "+fltEnergyModifier);
space_crafting.setComponentGeneralEfficiency(objComponent, fltGeneralModifier);
space_crafting.setComponentEnergyEfficiency(objComponent, fltEnergyModifier);
return;
}
boolean drainEnergyFromCapacitor(obj_id objShip, float fltEnergy, boolean boolOverride)
{
float fltCurrentEnergy = getShipCapacitorEnergyCurrent(objShip);
if(fltCurrentEnergy < fltEnergy)
{
if(boolOverride)
{
fltCurrentEnergy = 0;
}
else
{
return false; // not enough energy
}
}
else
{
fltCurrentEnergy = fltCurrentEnergy - fltEnergy;
}
setShipCapacitorEnergyCurrent(objShip, fltCurrentEnergy);
return true;
}
boolean drainEnergyFromShield(obj_id objShip, int intSide, float fltEnergy, boolean boolOverride)
{
if(intSide == FRONT)
{
float fltCurrentEnergy = getShipShieldHitpointsFrontCurrent(objShip);
if(fltCurrentEnergy < fltEnergy)
{
if(boolOverride)
{
fltCurrentEnergy = 0;
}
else
{
return false; // not enough energy
}
}
else
{
fltCurrentEnergy = fltCurrentEnergy - fltEnergy;
}
setShipShieldHitpointsFrontCurrent(objShip, fltCurrentEnergy);
return true;
}
else
{
float fltCurrentEnergy = getShipShieldHitpointsBackCurrent(objShip);
if(fltCurrentEnergy < fltEnergy)
{
if(boolOverride)
{
fltCurrentEnergy = 0;
}
else
{
return false; // not enough energy
}
}
else
{
fltCurrentEnergy = fltCurrentEnergy - fltEnergy;
}
setShipShieldHitpointsBackCurrent(objShip, fltCurrentEnergy);
return true;
}
}
boolean addEnergyToCapacitor(obj_id objShip, int intWeaponCapacitor, float fltEnergy, boolean boolOverride)
{
float fltCurrentEnergy = getShipCapacitorEnergyCurrent(objShip);
float fltMaximumEnergy = getShipCapacitorEnergyMaximum(objShip);
float fltDifference = fltMaximumEnergy - fltCurrentEnergy;
if(fltDifference < fltEnergy)
{
if(boolOverride)
{
fltCurrentEnergy = fltMaximumEnergy;
}
else
{
return false; // not enough energy
}
}
else
{
fltCurrentEnergy = fltCurrentEnergy + fltEnergy;
}
setShipCapacitorEnergyCurrent(objShip, fltCurrentEnergy);
return true;
}
boolean addEnergyToShield(obj_id objShip, int intSide, float fltEnergy, boolean boolOverride)
{
if(intSide == FRONT)
{
float fltCurrentEnergy = getShipShieldHitpointsFrontCurrent(objShip);
float fltMaximumEnergy = getShipShieldHitpointsFrontMaximum(objShip);
float fltDifference = fltMaximumEnergy - fltCurrentEnergy;
if(fltDifference < fltEnergy)
{
if(boolOverride)
{
fltCurrentEnergy = fltMaximumEnergy;
}
else
{
return false; // not enough energy
}
}
else
{
fltCurrentEnergy = fltCurrentEnergy + fltEnergy;
}
setShipShieldHitpointsFrontCurrent(objShip, fltCurrentEnergy);
return true;
}
else
{
float fltCurrentEnergy = getShipShieldHitpointsBackCurrent(objShip);
float fltMaximumEnergy = getShipShieldHitpointsBackMaximum(objShip);
float fltDifference = fltMaximumEnergy - fltCurrentEnergy;
if(fltDifference < fltEnergy)
{
if(boolOverride)
{
fltCurrentEnergy = fltMaximumEnergy;
}
else
{
return false; // not enough energy
}
}
else
{
fltCurrentEnergy = fltCurrentEnergy + fltEnergy;
}
setShipShieldHitpointsBackCurrent(objShip, fltCurrentEnergy);
return true;
}
}
// transfer
boolean transferFrontShieldToBack(obj_id objShip, float fltPercentage)
{
float fltCurrentEnergy = getShipShieldHitpointsFrontCurrent(objShip);
float fltEnergy = fltCurrentEnergy * fltPercentage;
if(drainEnergyFromShield(objShip, space_combat.FRONT, fltEnergy, false))
{
addEnergyToShield(objShip, space_combat.BACK, fltEnergy, true);
return true;
}
else
{
return false;
}
}
boolean transferBackShieldToFront(obj_id objShip, float fltPercentage)
{
float fltCurrentEnergy = getShipShieldHitpointsBackCurrent(objShip);
float fltEnergy = fltCurrentEnergy * fltPercentage;
if(drainEnergyFromShield(objShip, space_combat.BACK, fltEnergy, false))
{
addEnergyToShield(objShip, space_combat.FRONT, fltEnergy, true);
return true;
}
else
{
return false;
}
}
boolean reinforceShieldsFromCapacitor(obj_id objShip, float fltPercentage)
{
float fltCurrentEnergy = getShipCapacitorEnergyCurrent(objShip);
//sendSystemMessageTestingOnly(objShip, "Getting current shipCapacitorEnergy... Value retrieved is: "+fltCurrentEnergy);
//debugServerConsoleMsg( null, "+++ space_combat . reinforceShieldsFromCapacitor +++ Getting current shipCapacitorEnergy... Value retrieved is: "+fltCurrentEnergy );
float fltEnergy = fltCurrentEnergy * fltPercentage;
//debugServerConsoleMsg( null, "+++ space_combat . reinforceShieldsFromCapacitor +++ Percentage of capacitor used is: "+fltPercentage+" Amount of resulting capacitor energy used is "+fltEnergy);
//sendSystemMessageTestingOnly(objShip, "Percentage of capacitor used is: "+fltPercentage+" Amount of resulting capacitor energy used is "+fltEnergy);
if(drainEnergyFromCapacitor(objShip, fltEnergy, false))
{
//following lines are for debug purposes only. YANK THEM WHEN DONE!!!!!!!
//sendSystemMessageTestingOnly(objShip, "Successfuly drained energy from capacitor ");
//debugServerConsoleMsg( null, "+++ space_combat . reinforceShieldsFromCapacitor +++ Successfuly drained energy from capacitor ");
fltCurrentEnergy = getShipCapacitorEnergyCurrent(objShip);
//debugServerConsoleMsg( null, "+++ space_combat . reinforceShieldsFromCapacitor +++ current capacitor energy, post-drain, is: "+fltCurrentEnergy);
addEnergyToShield(objShip, space_combat.FRONT, fltEnergy / 2, true);
//sendSystemMessageTestingOnly(objShip, "adding energy to front shield ");
//debugServerConsoleMsg( null, "+++ space_combat . reinforceShieldsFromCapacitor +++ adding energy to front shield ");
addEnergyToShield(objShip, space_combat.BACK, fltEnergy / 2, true);
return true;
}
return false;
}
// i pass in objShip into the functions below for future expansions of the disabling system
// it's a distinct possiblity we will expand this to a per chassis concept.
boolean isComponentMandatory(obj_id objShip, int intSlot)
{
for(int intI = 0; intI < MANDATORY_COMPONENTS.length; intI++)
{
if(intSlot == MANDATORY_COMPONENTS[intI])
{
return true;
}
}
return false;
}
boolean isShipDisabled(obj_id objShip, int intSlot)
{
if(isComponentMandatory(objShip, intSlot))
{
return true;
}
return false;
}
boolean isShipDisabled(obj_id objShip)
{
// check if the mandatory components are disabled
for(int intI = 0; intI < MANDATORY_COMPONENTS.length; intI++)
{
if(isShipComponentDisabled(objShip, MANDATORY_COMPONENTS[intI]))
{
return true;
}
}
return false;
}
void killSpacePlayer(obj_id objShip)
{
//we find the closest station
// we get a random point around the station
// we teleport the player
// we tell them they need to fix their shit or go home.
LOG("space", "Killing " + objShip);
resizeable obj_id[] objPlayers = space_utils.getPlayersInShip(objShip);
if(utils.hasScriptVar(objShip, "intEjecting"))
{
utils.removeScriptVar(objShip, "intEjecting");
}
if(hasObjVar(objShip, "intAlarmsOn"))
{
space_crafting.turnOnInteriorAlarms(objShip);
}
space_crafting.fixAllPlasmaConduits(objShip);
clearHyperspace(objShip);
if(objPlayers != null)
{
for(int intI = 0; intI < objPlayers.length; intI++)
{
// Fail smuggler missions in space when they die
groundquests.sendSignal(objPlayers[intI], "smugglerEnemyIncap");
string_id strSpam = new string_id("space/space_interaction", "your_ship_esploded");
sendSystemMessage(objPlayers[intI], strSpam);
CustomerServiceLog("space_death", "Wounding " + objPlayers[intI] + " because " + objShip + " exploded", objPlayers[intI]);
healing.healClone(objPlayers[intI], false);
}
}
ship_ai.unitRemoveFromAllAttackTargetLists(objShip);
ship_ai.unitSetAutoAggroImmune(objShip, true); // auto-aggro immune for infinity
space_pilot_command.allPurposeShipComponentReset(objShip);
space_transition.clearOvertStatus(objShip);
obj_id objPilot = getPilotId(objShip);
if(utils.hasScriptVar(objShip, "intPVPKill"))
{
space_crafting.repairDamageToPercentage(objPilot, objShip, 1.0f);
}
clearDeathFlags(objShip);
clearCondition(objShip, CONDITION_EJECT);
if(space_battlefield.isInBattlefield(objShip))
{
CustomerServiceLog("battlefield", "Battlefield death for " + objShip + " removing them from " + getLocation(objShip), getOwner(objShip));
doBattlefieldRepairCheck(objShip);
location locTest = getLocationObjVar(objShip, "battlefield.locRespawnLocation");
if(locTest == null)
{
locTest = getLocation(objShip);
locTest.x = 0;
locTest.y = 0;
locTest.z = 0;
//LOG("space", "No station, warping to "+locTest);
warpPlayer(objShip, locTest.area, locTest.x, locTest.y, locTest.z, null, locTest.x, locTest.y, locTest.z, null, true);
}
else
{
removeObjVar(objShip, "battlefield.locRespawnLocation");
warpPlayer(objShip, locTest.area, locTest.x, locTest.y, locTest.z, null, locTest.x, locTest.y, locTest.z, null, true);
}
return;
}
else
{
obj_id objClosestStation = getClosestSpaceStation(objShip);
if(isIdValid(objClosestStation) && (!exists(objClosestStation)))
{
objClosestStation = null;
}
if(!isIdValid(objClosestStation))
{
if(isIdValid(objPilot))
{
sendSystemMessageTestingOnly(getPilotId(objShip), "Respawn failure. You don't have any space stations defined, or no quest manager for them to register with. Sorry :(");
}
location locTest = getLocation(objShip);
locTest.x = 0;
locTest.y = 0;
locTest.z = 0;
//////LOG("space", "No station, warping to "+locTest);
// HACK HACK HACK SINCE SETTRANSFORM IS 9 KINDS OF FUCKED UP RIGHT NOW
warpPlayer(objShip, locTest.area, locTest.x, locTest.y, locTest.z, null, locTest.x, locTest.y, locTest.z, null, true);
}
else
{
transform trTest = space_utils.getRandomPositionInSphere(getTransform_o2p(objClosestStation), 425f, 450f, false);
vector vctTest = space_utils.getVector(objClosestStation);
CustomerServiceLog("space_loot", "Killing " + objShip + " and sending them to " + getLocation(objClosestStation), getOwner(objShip));
transform trFinalTransform = space_utils.faceTransformToVector(trTest, vctTest);
//////LOG("space", "station, warping to "+vctTest);
// HACK HACK HACK SINCE SETTRANSFORM IS 9 KINDS OF FUCKED UP RIGHT NOW
location locTest = getLocation(objShip);
space_utils.openCommChannelAfterLoad(objShip, objClosestStation);
warpPlayer(objShip, locTest.area, vctTest.x, vctTest.y, vctTest.z, null, vctTest.x, vctTest.y, vctTest.z, null, true);
setTransform_o2p(objShip, trFinalTransform);
}
}
return;
}
obj_id getClosestSpaceStation(obj_id objShip)
{
obj_id objQuestManager = null;
if(!utils.checkConfigFlag("ScriptFlags", "liveSpaceServer"))
{
try
{
objQuestManager = getNamedObject(space_quest.QUEST_MANAGER);
}
catch(Throwable err)
{
return null;
}
}
else
{
objQuestManager = getNamedObject(space_quest.QUEST_MANAGER);
}
if(!isIdValid(objQuestManager))
{
//////LOG("space", "No quest manager registered for getclosestspacestation");
return null;
}
location locTest = getLocation(objShip);
obj_id[] objSpaceStations = utils.getObjIdArrayScriptVar(objQuestManager, "objSpaceStations");
if(objSpaceStations == null || objSpaceStations.length == 0)
{
//////LOG("space", "No stations registered for getclosestspacestation");
return null;
}
float fltDistance = 320000;
obj_id objClosestStation = null;
//LOG("space", "objSpaceStations length is "+objSpaceStations.length);
for(int intI = 0; intI < objSpaceStations.length; intI++)
{
// LOOOP! GLORIOUS LOOPS!
location locStation = getLocation(objSpaceStations[intI]);
//LOG("space", "got station "+objSpaceStations[intI]+" at "+locStation);
float fltTest = getDistance(locTest, locStation);
//LOG("space", "distance is "+fltTest+" old distance is "+fltDistance);
//LOG("space", "locTest is "+locTest);
if(fltTest < fltDistance)
{
objClosestStation = objSpaceStations[intI];
//LOG("space", "setting closest station to "+objClosestStation);
fltDistance = fltTest;
}
}
// end loop :(
return objClosestStation;
}
//---------------------------------------------------------------------- Player special ability functions
void initializeCommandTimer(obj_id pilot, int commandDelay)
{
int time = getGameTime();
time = time + commandDelay;
utils.setScriptVar(pilot, "cmd.commandTimeStamp", time);
dictionary outparams = new dictionary();
if(!messageTo(pilot, "commandTimerTimeout", outparams, (float) (commandDelay), false))
debugServerConsoleMsg(null, "+++ space_combat . initializeCommandTimer +++ FAILED to send messageTo. ObjID of pilot was: " + pilot + " amount of time delay was: " + commandDelay);
}
boolean commandTimePassed(obj_id pilot)
{
int intCurrentTime = getGameTime();
int intLastTime = utils.getIntScriptVar(pilot, "cmd.commandTimeStamp");
if(intCurrentTime < intLastTime)
{
string_id strSpam = new string_id("space/space_interaction", "pilot_command_delay");
sendSystemMessage(pilot, strSpam);
if((intLastTime - intCurrentTime) < 60)
{
//sendSystemMessageTestingOnly(pilot, "It looks like you might be ready in just a minute.");
string_id strSpam2 = new string_id("space/space_interaction", "pilot_command_delay_bit");
sendSystemMessage(pilot, strSpam2);
}
else if((intLastTime - intCurrentTime) < 120)
{
//sendSystemMessageTestingOnly(pilot, "It looks like you might be ready in a couple more minutes...");
string_id strSpam2 = new string_id("space/space_interaction", "pilot_command_delay_some");
sendSystemMessage(pilot, strSpam2);
}
return false;
}
return true;
}
boolean doReactorPumpPulse(obj_id pilot, obj_id ship)
{
if(!isShipSlotInstalled(ship, ship_chassis_slot_type.SCST_reactor))
{
debugServerConsoleMsg(null, "+++ SPACE COMMAND . doReactorPumpPulse +++ No reactor onboard. What the!?.");
return false;
}
flightDroidVocalize(ship, 1);
if(space_combat.doesReactorScram(pilot, ship, "level1command"))
{
space_combat.scramReactor(pilot, ship);
return true;
}
if(isEfficiencyModified(ship_chassis_slot_type.SCST_reactor, ship))
{
setEfficiencyModifier(ship_chassis_slot_type.SCST_reactor, ship, 1.0f, 1.0f);
string_id strSpam = new string_id("space/space_interaction", "aborting_reactor_pump");
sendSystemMessage(pilot, strSpam);
}
else
{
string_id strSpam = new string_id("space/space_interaction", "do_reactor_pump_one");
string_id strSpamTwo = new string_id("space/space_interaction", "do_reactor_pump_two");
sendSystemMessage(pilot, strSpam);
sendSystemMessage(pilot, strSpamTwo);
float rndReactorUpgradeEffect = rand(1.1f, 1.4f);
debugServerConsoleMsg(null, "+++ SPACE COMMAND . doReactorPumpPulse +++ Looks like the upgrade will be: " + rndReactorUpgradeEffect);
setEfficiencyModifier(ship_chassis_slot_type.SCST_reactor, ship, rndReactorUpgradeEffect, 1.0f);
setEfficiencyModifier(ship_chassis_slot_type.SCST_engine, ship, rndReactorUpgradeEffect, 1.0f);
int pumpPulseLoops = (int) (rand(1.0f, 10.0f));
dictionary outparams = new dictionary();
outparams.put("ship", ship);
outparams.put("loops", pumpPulseLoops);
outparams.put("pilot", pilot);
if(!messageTo(ship, "reactorPumpPulseTimeout", outparams, 5.0f, false))
debugServerConsoleMsg(null, "+++ SPACE COMMAND . doReactorPumpPulse +++ FAILED to send messageTo. ObjID of ship was: " + ship + " objID of pilot was: " + pilot + " number of loops was: " + pumpPulseLoops);
}
return true;
}
boolean doesReactorScram(obj_id pilot, obj_id ship, string difficultyOfCommand)
{
if(!isIdValid(pilot) || !isIdValid(ship))
return true; //SCRAM THE REACTOR IF THINGS LOOK ALL FARKED UP
int successLevel = doPilotCommandSkillCheck(pilot, difficultyOfCommand);
if(successLevel > 4)
return true;
return false;
}
void scramReactor(obj_id pilot, obj_id ship)
{
string_id strSpam = new string_id("space/space_interaction", "scramming_reactor");
sendSystemMessage(pilot, strSpam);
space_utils.setComponentDisabled(ship, ship_chassis_slot_type.SCST_reactor, true);
space_utils.setComponentDisabled(ship, ship_chassis_slot_type.SCST_engine, true);
if(isShipSlotInstalled(ship, ship_chassis_slot_type.SCST_booster))
space_utils.setComponentDisabled(ship, ship_chassis_slot_type.SCST_booster, true);
//Close Ships wings, if it has them
if(getShipHasWings(ship))
clearCondition(ship, CONDITION_WINGS_OPENED);
string cefPlayBackHardpoint = targetHardpointForCefPlayback(ship);
playClientEffectObj(pilot, "clienteffect/space_command/scram_reactor_shuttingdown_siren.cef", ship, cefPlayBackHardpoint); //PLAY SOME COOL IFF-PULSE EFFECT HERE
playClientEffectObj(pilot, "clienteffect/space_command/scram_reactor_shutdown_engine.cef", ship, cefPlayBackHardpoint);
int scramLoops = (int) (rand(1.0f, 10.0f));
dictionary outparams = new dictionary();
outparams.put("ship", ship);
outparams.put("loops", scramLoops);
outparams.put("pilot", pilot);
messageTo(ship, "unScramReactor", outparams, 5.0f, false);
}
int getPlayerCommandSkill(obj_id pilot)
{
int playerSkill = 0;
if(hasSkill(pilot, "pilot_rebel_navy_master") || hasSkill(pilot, "pilot_imperial_navy_master") || hasSkill(pilot, "pilot_neutral_master"))
playerSkill = 10;
else if(hasSkill(pilot, "pilot_imperial_navy_procedures_04") || hasSkill(pilot, "pilot_neutral_procedures_04") || hasSkill(pilot, "pilot_rebel_navy_procedures_04"))
playerSkill = 7;
else if(hasSkill(pilot, "pilot_imperial_navy_procedures_03") || hasSkill(pilot, "pilot_neutral_procedures_03") || hasSkill(pilot, "pilot_rebel_navy_procedures_03"))
playerSkill = 5;
else if(hasSkill(pilot, "pilot_imperial_navy_procedures_02") || hasSkill(pilot, "pilot_neutral_procedures_02") || hasSkill(pilot, "pilot_rebel_navy_procedures_02"))
playerSkill = 3;
else
playerSkill = 1;
return playerSkill;
}
int getAttackerSkill(obj_id targetShip)
{
const int CONST_PILOT_FAIL = 0;
int pilotSkill = 0;
if(ship_ai.isPlayerShip(targetShip))
{
obj_id playerPilot = space_utils.getCommandExecutor(targetShip);
if(isIdValid(playerPilot))
pilotSkill = getPlayerCommandSkill(playerPilot);
}
else if(hasObjVar(targetShip, "ship.pilotType"))
{
string strPilot = getStringObjVar(targetShip, "ship.pilotType");
if(strPilot == null)
{
debugServerConsoleMsg(null, "space_combat.getNpcPilotSkill -- strPilot checked out as NULL");
pilotSkill = CONST_PILOT_FAIL;
}
else if(strPilot == "ace")
pilotSkill = 10;
else if(strPilot == "average")
pilotSkill = 5;
else if(strPilot == "rookie")
pilotSkill = 2;
else
pilotSkill = CONST_PILOT_FAIL;
return pilotSkill;
}
return CONST_PILOT_FAIL;
}
boolean doIffScramble(obj_id pilot, obj_id ship)
{
debugServerConsoleMsg(null, "space_combat.doIffScramble ++ entered function");
//find out whos attacking me
obj_id[] myAttackers = ship_ai.unitGetWhoIsTargetingMe(ship);
if((myAttackers == null) || (myAttackers.length == 0))
{
string_id strSpam = new string_id("space/space_interaction", "iff_spoof_dont_bother");
sendSystemMessage(pilot, strSpam);
return false;
}
flightDroidVocalize(ship, 1);
//find out if we manage to do this
int rnd = rand(1, 10);
int playerSkill = getPlayerCommandSkill(pilot);
int spoofedAttackers = 0;
dictionary params = new dictionary();
int numberOfJammedDudes = 0; //total number of dudes we've jammed
int sumTotalOfSkillCheckDeltas = 0; //total number of all the delta's
int lowestSkillCheckDelta = 0;
int highestSkillCheckDelta = 0;
//send out a stop-attack to whoever's attacking me
for(int i = 0; i < myAttackers.length; i++)
{
if(isIdValid(myAttackers[i]))
{
obj_id thisAttacker = myAttackers[i];
if(exists(thisAttacker))
{
if(!space_utils.isPlayerControlledShip(myAttackers[i]))
{
int attackerSkill = getAttackerSkill(myAttackers[i]);
if((playerSkill + rnd) > (attackerSkill + 3))
{
debugServerConsoleMsg(null, "space_combat.doIffScramble ++ iff scrambled ship " + thisAttacker + " with my skill " + playerSkill + " and botskill " + attackerSkill + " and rnd " + rnd);
ship_ai.unitRemoveAttackTarget(thisAttacker, ship);
// GOING TO TRY TO PLAY THE CEF ON JAMMED SHIPS IN THIS LOCATION, AS OPPOSED TO THEIR OWN SPACE_AI, WHICH I'VE HAD NO LUCK WITH.
//string cefPlayBackHardpoint = space_combat.targetHardpointForCefPlayback(thisAttacker);
//playClientEffectObj(jammerPilot, "clienteffect/space_command/shp_shocked_radio_01.cef", thisAttacker, cefPlayBackHardpoint);
playClientEffectObj(ship, "clienteffect/space_command/shp_shocked_radio_01_noshake.cef", thisAttacker, "");
spoofedAttackers++;
int skillCheckDelta = (playerSkill + rnd) - (attackerSkill + 3);
sumTotalOfSkillCheckDeltas += skillCheckDelta;
numberOfJammedDudes++;
/* COMMENTED OUT BECAUSE WE NO LONGER PUT LOOPS ON JAMMED SUBJECTS, NOW WE USE MATT BOGUE'S NEWISH unitSetAgroImmuneTime
params.put( "loopsleft", skillCheckDelta );
params.put( "targetship", ship );
params.put( "jammerPilot", pilot );
messageTo( myAttackers[i], "iAmSpoofed", params, 5.0f, false );
*/
}
else
debugServerConsoleMsg(null, "space_combat.doIffScramble ++ iff did NOT scramble ship " + thisAttacker + " with my skill " + playerSkill + " and botskill " + attackerSkill + " and rnd " + rnd);
}
}
}
}
if(spoofedAttackers <= 0)
{
string_id strSpam = new string_id("space/space_interaction", "iff_spoofing_unsuccessful");
sendSystemMessage(pilot, strSpam);
//disableWeaponry(ship, true); //USED TO DISABLE WEAPONS TO ADD A 'PENALTY' TO FAILING A SCRAMBLE. COMMENTING THAT OUT NOW
dictionary outparams = new dictionary();
outparams.put("pilot", pilot);
outparams.put("ship", ship);
messageTo(pilot, "unIffScramble", outparams, 360.0f, false);
return false;
}
// else
// playClientEffectObj(pilot, "clienteffect/space_scram_spark.cef", ship, "astromech"); //PLAY SOME COOL IFF-PULSE EFFECT HERE
//immune time from the baddies is equal to what would have been the loops.
float agroImmuneTime = (sumTotalOfSkillCheckDeltas / numberOfJammedDudes) * 5;
if(agroImmuneTime < 20.0f)
agroImmuneTime = 20.0f;
ship_ai.unitSetAutoAggroImmuneTime(ship, agroImmuneTime);
string_id strSpam = new string_id("space/space_interaction", "iff_spoofed");
sendSystemMessage(pilot, strSpam);
dictionary outparams = new dictionary();
outparams.put("pilot", pilot);
outparams.put("ship", ship);
messageTo(pilot, "unIffScramble", outparams, 360.0f, false);
return true;
}
void disableWeaponry(obj_id ship, boolean disable)
{
for(int chassisSlot = ship_chassis_slot_type.SCST_weapon_first; chassisSlot < ship_chassis_slot_type.SCST_weapon_last; chassisSlot++)
{
if(isShipSlotInstalled(ship, chassisSlot))
{
if(disable == true)
space_utils.setComponentDisabled(ship, chassisSlot, true);
else
{
float fltCurrentHitPoints = getShipComponentHitpointsCurrent(ship, chassisSlot);
if(fltCurrentHitPoints > 0)
{
space_utils.setComponentDisabled(ship, chassisSlot, false);
recalculateEfficiency(chassisSlot, ship); // recalc based on damage since you've got the power
}
}
}
}
return;
}
string[] getProgrammedDroidCommands(obj_id objPlayer)
{
// only usable while flying
obj_id objShip = space_transition.getContainingShip(objPlayer);
if(!isIdValid(objShip))
{
return null;
}
//Look in the droid datapad slot.
obj_id objControlDevice = getDroidControlDeviceForShip(objShip);
if(!isIdValid(objControlDevice))
{
return null;
}
obj_id objDataPad = utils.getDatapad(objControlDevice);
if(!isIdValid(objDataPad))
{
////////LOG("space", "No datapad defined for "+objControlDevice);
return null;
}
obj_id[] objContents = utils.getContents(objDataPad);
resizeable string[] strCommands = new string[];
for(int intI = 0; intI < objContents.length; intI++)
{
if(hasObjVar(objContents[intI], "strDroidCommand"))
{
string strTest = getStringObjVar(objContents[intI], "strDroidCommand");
strCommands = utils.addElement(strCommands, strTest);
}
}
return strCommands;
}
string[] getDroidCommands(obj_id objPlayer)
{
string[] strRawCommands = getCommandListingForPlayer(objPlayer);
resizeable string[] strDroidCommands = new string[0];
for(int intI = 0; intI < strRawCommands.length; intI++)
{
int intIndex = strRawCommands[intI].indexOf("droidcommand");
if(intIndex > -1)
{
strDroidCommands = utils.addElement(strDroidCommands, strRawCommands[intI]);
}
}
if(strDroidCommands.length > 0)
{
return strDroidCommands;
}
else
{
return null;
}
}
void grantCapitalShipSequenceRewardsAndCreditForKills(obj_id objDefender)
{
//////////LOG("space", "getting kill percentages");
dictionary dctParams = getKillPercentages(objDefender);
if(dctParams == null)
{
//////////LOG("space", "NULL");
return; //??????
}
obj_id[] objAttackers = dctParams.getObjIdArray("objAttackers");
obj_id objWinner = dctParams.getObjId("objWinner");
float[] fltPercentages = dctParams.getFloatArray("fltPercentages");
obj_id[] objWinningMembers = utils.getObjIdArrayLocalVar(objDefender, "objWinningMembers"); // if this is null, no groups involves
utils.removeLocalVar(objDefender, "objAttackers");
utils.removeLocalVar(objDefender, "objWinner");
utils.removeLocalVar(objDefender, "fltPercentages");
utils.removeLocalVar(objDefender, "objWinningMembers");
// percentages is how much damage they did
// obj_id attackers is who did it
// winner is the person who got the most damage.
// winner could be a group! that is important
// winning members i sthe group members who particiapted.. they all get credit and stuff
// we grant "credit" to everyone over the minimum
// then we make our loot
// and grant looting rights
//////////LOG("space", "length of array returned is "+objAttackers.length);
int intXP = 500;
if(objAttackers != null)
{
for(int intI = 0; intI < objAttackers.length; intI++)
{
//////////LOG("space", "objAttackers["+intI+"] is "+objAttackers[intI]);
if(fltPercentages[intI] > MINIMUM_DAMAGE_THRESHOLD)
{
// YOU GET CREDIT!
//////////LOG("space", "nofitying "+objAttackers[intI]);
notifyAttacker(objAttackers[intI], objDefender, fltPercentages[intI]);
// you get some xp too
int intAmount = intXP;
float fltTest = (float) intAmount; // casting so i dont screw up
fltTest = fltTest * fltPercentages[intI];
intAmount = (int) fltTest;
xp.grant(getPilotId(objAttackers[intI]), xp.SPACE_COMBAT_GENERAL, intAmount, true);
// whatever reward stuff goes here..
}
}
}
return;
}
void flightDroidVocalize(obj_id ship, int vocalizePriority)
{
flightDroidVocalize(ship, vocalizePriority, null);
}
void flightDroidVocalize(obj_id ship, int vocalizePriority, prose_package pp)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.flightDroidVocalize: ############################################################# Just Entered function.");
if(!isIdValid(ship))
{
return;
}
// freak-out level of 1, 2, or 3. Lower number should freak more majorly
// Will check for presence of a droid before doing this.
obj_id droidPcd = getDroidControlDeviceForShip(ship);
debugServerConsoleMsg(null, "SPACE_COMBAT.flightDroidVocalize: Ship's droidPCD is: " + droidPcd);
if(!isIdValid(droidPcd)) // If no droid on-board, we're wasting out time in here. Bail out.
{
debugServerConsoleMsg(null, "SPACE_COMBAT.flightDroidVocalize: Wanted to vocalize, but no droid PCD assigned to ship, so no vocalize.");
return;
}
if(utils.hasLocalVar(ship, "droidcmd.muteDroid"))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.flightDroidVocalize: Wanted to vocalize, but ship has muteDroid localvar, so aborted.");
return;
}
obj_id player = getShipPilot(ship);
int currentTime = getGameTime();
int storedVocalizeTime = 0;
if(utils.hasLocalVar(ship, "droidVocTime"))
storedVocalizeTime = utils.getIntLocalVar(ship, "droidVocTime");
int timeDelta = currentTime - storedVocalizeTime;
if(vocalizePriority < 2) //HIGH priority. VOCALIZE ASAP, unless we just vocalized!
{
if(!utils.hasLocalVar(ship, "droidVocTime") || timeDelta > 3)
{
utils.setLocalVar(ship, "droidVocTime", getGameTime());
vocalizeSpaceDroid(droidPcd, player, ship, vocalizePriority);
if(pp != null)
{
obj_id droid = callable.getCDCallable(droidPcd);
if(isIdValid(droid))
{
space_utils.tauntPlayer(player, droid, pp);
}
else if(space_crafting.isFlightComputerController(droidPcd))
{
space_utils.tauntPlayer(player, droidPcd, pp);
}
else
{
debugServerConsoleMsg(null, "SPACE_COMBAT.flightDroidVocalize: ERROR! COULD NOT FIND A VALID DROID OBJ_ID. space_utils.tauntPlayer call loc #1");
}
}
}
return;
}
else if(vocalizePriority < 3) //MEDIUM priority. Vocalize if we didn't recently vocalize.
{
if(!utils.hasLocalVar(ship, "droidVocTime") || timeDelta > 7)
{
utils.setLocalVar(ship, "droidVocTime", getGameTime());
obj_id droid = callable.getCDCallable(droidPcd);
if(isIdValid(droid))
{
space_utils.tauntPlayer(player, droid, pp);
}
else if(space_crafting.isFlightComputerController(droidPcd))
{
space_utils.tauntPlayer(player, droidPcd, pp);
}
else
{
debugServerConsoleMsg(null, "SPACE_COMBAT.flightDroidVocalize: ERROR! COULD NOT FIND A VALID DROID OBJ_ID. space_utils.tauntPlayer call loc #2");
}
vocalizeSpaceDroid(droidPcd, player, ship, vocalizePriority);
}
return;
}
else //LOW priority. Vocalize if full quiet time has elapsed.
{
if(!utils.hasLocalVar(ship, "droidVocalizationQueued"))
{
dictionary outparams = new dictionary();
outparams.put("ship", ship);
outparams.put("vocalizePriority", vocalizePriority);
int droidVocalizeDelay = rndDroidVocalizeDelay();
utils.setLocalVar(ship, "droidVocalizationQueued", droidVocalizeDelay);
messageTo(ship, "flightDroidVocalize", outparams, droidVocalizeDelay, false);
return;
}
else
{
if(utils.getIntLocalVar(ship, "droidVocalizationQueued") >= getGameTime())
{
if(!utils.hasLocalVar(ship, "droidVocTime") || timeDelta > 7)
{
utils.setLocalVar(ship, "droidVocTime", getGameTime());
vocalizeSpaceDroid(droidPcd, player, ship, vocalizePriority);
}
utils.removeLocalVar(ship, "droidVocalizationQueued");
}
}
}
return;
}
int rndDroidVocalizeDelay()
{
int currentTime = getGameTime();
int rndVocDelay = (int) (rand(5.0f * DROID_VOCALIZE_DELAY_CONST, 30.0f * DROID_VOCALIZE_DELAY_CONST));
int newProjectedVocTime = currentTime + rndVocDelay;
return newProjectedVocTime;
}
void vocalizeSpaceDroid(obj_id droidPcd, obj_id player, obj_id ship, int vocalizePriority)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: ############################################################# Just Entered function.");
//figure out what droidType is
obj_id droid = null;
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: Just read in pet.current ObjIdScriptVar off of droidPCD. The droidPcd we grabbed from was: " + droidPcd + " and the pet.current obj_id was: " + droid);
int droidSpecies = 0;
if(space_crafting.isFlightComputerController(droidPcd))
{
droidSpecies = 216;
}
else
{
droid = callable.getCDCallable(droidPcd);
droidSpecies = getSpecies(droid);
}
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: just got the species off the droid. The value was: " + droidSpecies);
int speciesChecksum = dataTableSearchColumnForInt(droidSpecies, 0, DROID_VOCALIZE_DATATABLE);
if(speciesChecksum == -1)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: speciesChecksum failed out as being -1");
return;
}
//if its a high priority vocalization, play one of three damage exclamations
// if its a medium priority vocalization, play one of three confirmations
// if its a low priority vocalization, play one of three chatty comments
int column = 0;
if(vocalizePriority == 1)
column = 7;
else if(vocalizePriority == 2)
column = rand(4, 6);
else
column = rand(1, 3);
int droidSpeciesRow = dataTableSearchColumnForInt(droidSpecies, 0, DROID_VOCALIZE_DATATABLE);
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: Found the droid species designator int in row: " + droidSpeciesRow + " of the DROID_VOCALIZE_DATATABLE");
string droidVocalizationEffectFile = dataTableGetString(DROID_VOCALIZE_DATATABLE, droidSpeciesRow, column);
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: Droid vocalization we are going to play is from file:" + droidVocalizationEffectFile);
if(droidVocalizationEffectFile == null)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.vocalizeSpaceDroid: droidVocalizationEffectFile was null. Kicking out! ");
return;
}
else if(droidSpecies == 214 || droidSpecies == 215 || droidSpecies == 216)
playClientEffectObj(player, droidVocalizationEffectFile, ship, "engine_glow1"); // no astromech hardpoint if the ship doesn't have an astromech, use something else
else
playClientEffectObj(player, droidVocalizationEffectFile, ship, "astromech");
return;
}
string targetHardpointForCefPlayback(obj_id ship)
{
string templateName = utils.getTemplateFilenameNoPath(ship);
string shipUsesThis = dataTableGetString(space_crafting.STARSHIP_DROID_TABLE, templateName, "usesDroidOrFlightComputer");
debugServerConsoleMsg(null, "+++ SPACE_CRAFTING . Got shipUsesThis. It was: " + shipUsesThis);
if(shipUsesThis == null || shipUsesThis == "")
{
debugServerConsoleMsg(null, "SPACE_COMBAT.targetHardpointForCefPlayback: shipUsesThis failed out as being -1");
//return null;
return "engine_glow1"; //GOING TO EXPERIMENT WITH RETURNING A DEFAULT HARDPOINT FOR CATCHALL CEF PLAYBACK LOCATION
}
if(shipUsesThis == "astromech")
return "astromech";
return "engine_glow1";
}
void createFlightDroidFromData(obj_id petControlDevice, obj_id objContainer)
{
string creatureName = getStringObjVar(petControlDevice, "pet.creatureName");
if(creatureName == null || creatureName == "")
return;
obj_id datapad = getContainedBy(petControlDevice);
if(!isIdValid(datapad))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.createFlightDroidFromData: FAILURE. Kicking out after databad isIdValid check failed. Datapad was: " + datapad);
return;
}
obj_id master = getContainedBy(datapad);
if(!isIdValid(master))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.createFlightDroidFromData: FAILURE. Kicking out after master isIdValid check failed. Master was: " + master);
return;
}
if(!hasScript(master, "ai.pet_master"))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.createFlightDroidFromData: No ai.pet_master script detected. Adding it.");
attachScript(master, "ai.pet_master");
}
obj_id pet = null;
if(!isIdValid(objContainer))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.createFlightDroidFromData: FIRST CUSTOM SPACEFLIGHT DROID CREATION BIT. objContainer isIdValid check failed. objContainer was: " + objContainer);
return;
}
else // it goes into a container
pet = create.object(creatureName, objContainer, false, true);
if(!isIdValid(pet))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.createFlightDroidFromData: FAILURE. new pet obj_id failed isIdValid check " + pet);
sendSystemMessage(master, pet_lib.SID_PRIVATE_HOUSE);
return;
}
sendDirtyObjectMenuNotification(petControlDevice);
callable.setCallableLinks(master, petControlDevice, pet);
if(hasObjVar(petControlDevice, "pet.crafted"))
{
pet_lib.setCraftedPetStatsByGrowth(petControlDevice, pet, 10);
if(ai_lib.aiGetNiche(pet) == NICHE_DROID)
{
pet_lib.initDroidCraftedInventoryDroid(pet, petControlDevice);
pet_lib.initDroidCraftedDatapadDroid(pet, petControlDevice);
pet_lib.initDroidPersonality(pet, petControlDevice);
pet_lib.initDroidRepairPower(pet, petControlDevice);
//pet_lib.initDroidArmor(pet, petControlDevice); //SHOULDN'T BE NECESSARY POST C.U.
}
}
// reduce stats due to vitality loss
pet_lib.reduceStatsForVitality(pet, petControlDevice);
//restore old damage and wounds:
pet_lib.restoreDamage(pet, petControlDevice);
//restore learned commands:
if(hasObjVar(petControlDevice, "ai.pet.command"))
{
pet_lib.initializePetCommandList(pet, petControlDevice);
}
if(hasObjVar(petControlDevice, "alreadyTrained"))
setObjVar(pet, "alreadyTrained", true);
if(hasObjVar(petControlDevice, pet_lib.VAR_PALVAR_BASE))
{
pet_lib.restoreCustomization(pet, petControlDevice);
}
// Perform droid module initialization
if(pet_lib.isDroidPet(pet)) // Copy module data objvars.
copyObjVar(petControlDevice, pet, "module_data");
string name = getAssignedName(petControlDevice);
setName(pet, name);
}
boolean removeFlightDroidFromShip(obj_id droidControlDevice, obj_id droid)
{
if(isIdValid(droidControlDevice))
{
debugServerConsoleMsg(null, "SPACE_COMBAT.removeFlightDroidFromShip: petControlDevice obj_id isIdValid check passed.");
obj_id currentPet = callable.getCDCallable(droidControlDevice);
debugServerConsoleMsg(null, "SPACE_COMBAT.removeFlightDroidFromShip: got the objIdScriptVar off of the pcd. currentPet obj_id value was: " + currentPet);
if(isIdValid(currentPet) && currentPet == droid)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.removeFlightDroidFromShip: currentPet checked out as a a valid obj_id, and it equals the pet obj_id that was passed into the function at start. Proceeding.");
pet_lib.savePetInfo(droid, droidControlDevice);
setObjVar(droidControlDevice, "pet.timeStored", getGameTime());
callable.setCDCallable(droidControlDevice, null);
}
}
//-- Destroy the object.
debugServerConsoleMsg(null, "+++ SPACE_COMBAT.removeFlightDroidFromShip: +++ destroying the pet now");
utils.setScriptVar(droid, "stored", true);
if(destroyObject(droid))
{
return true;
}
debugServerConsoleMsg(null, "+++ SPACE_COMBAT.removeFlightDroidFromShip: +++ WARNINGWARNING - FAILED TO DESTROY SELF");
return false;
}
//void openFlightComputerDatapad( obj_id navicomp, obj_id owner )
void openFlightComputerDatapad(obj_id navicompControlDevice, obj_id owner)
{
//obj_id itemControlDevice = getObjIdObjVar( navicomp, "item.controlDevice" );
obj_id navicompDPad = utils.getDatapad(navicompControlDevice);
if(!isIdValid(navicompDPad))
{
debugServerConsoleMsg(null, "********** aaa.a navicompDPad objId failed isIdValid check, and we're kicking out.");
return;
}
obj_id myContainer = getContainedBy(navicompControlDevice);
obj_id yourPad = utils.getPlayerDatapad(owner);
if(myContainer != yourPad)
{
if(hasScript(myContainer, "item.tool.navicomputer_control_device"))
{
//I am being accessed while inside of a pcd So I will move from here to your pad:
putIn(navicompControlDevice, yourPad);
}
return;
}
utils.requestContainerOpen(owner, navicompDPad);
}
//returns TRUE if a control device is detected for this object, that there are appropriate obj_id objvars on both objects, and a dpad on the controller.
boolean isAnInitializedNavicomp(obj_id navicomp)
{
if(!isIdValid(navicomp))
return false;
if(!hasObjVar(navicomp, "item.controlDevice"))
return false;
obj_id controlDevice = getObjIdObjVar(navicomp, "item.controlDevice");
if(!isIdValid(controlDevice))
return false;
if(!hasObjVar(controlDevice, "item.current"))
return false;
obj_id currentItem = getObjIdObjVar(controlDevice, "item.current");
if(currentItem != navicomp)
return false;
obj_id controllerDpad = utils.getDatapad(controlDevice);
if(!isIdValid(controllerDpad))
return false;
return true;
}
boolean readyForEmergencyPower(obj_id ship)
{
if(!isIdValid(ship))
return false;
return true;
}
int[] getInstalledMissileWeapons(obj_id objShip)
{
resizeable int[] intWeapons = new int[0];
for(int intI = FIRST_WEAPON; intI < LAST_WEAPON; intI++)
{
if(isShipSlotInstalled(objShip, intI))
{
int intCrc = getShipComponentCrc(objShip, intI);
if((getShipComponentDescriptorWeaponIsMissile(intCrc)) && (!getShipComponentDescriptorWeaponIsCountermeasure(intCrc)))
{
intWeapons = utils.addElement(intWeapons, intI);
}
}
}
return intWeapons;
}
void emergencyCmdDamageToShipsSystems(obj_id pilot, obj_id ship, float percentToDamageTo, string clientEffect, int primaryComponent)
{
if(!isIdValid(ship))
return;
const int[] WEAPON_SLOTS = {
ship_chassis_slot_type.SCST_weapon_0,
ship_chassis_slot_type.SCST_weapon_1,
ship_chassis_slot_type.SCST_weapon_2,
ship_chassis_slot_type.SCST_weapon_3,
ship_chassis_slot_type.SCST_weapon_4,
ship_chassis_slot_type.SCST_weapon_5,
ship_chassis_slot_type.SCST_weapon_6,
ship_chassis_slot_type.SCST_weapon_7
};
if(clientEffect != "" && clientEffect != null)
{
playClientEffectObj(pilot, clientEffect, ship, targetHardpointForCefPlayback(ship));
}
float fltDamageToComponent = (getShipComponentHitpointsMaximum(ship, primaryComponent) * (percentToDamageTo / 100));
// validate the components
if((primaryComponent != NONE) && (primaryComponent != ALL_WEAPONS))
{
if(!isShipSlotInstalled(ship, primaryComponent))
{
//sendSystemMessageTestingOnly(pilot, "Trying to damage a component which is not installed.");
string_id strSpam = new string_id("space/space_interaction", "component_not_installed");
sendSystemMessage(pilot, strSpam);
return;
}
//for ( int intComponentToModify = ship_component_type.SCT_reactor; intComponentToModify < ship_component_type.SCT_num_types; intComponentToModify++ )
//{
float fltCurrentHitpoints = getShipComponentHitpointsCurrent(ship, primaryComponent);
float fltCurrentArmorHitpoints = getShipComponentArmorHitpointsCurrent(ship, primaryComponent);
fltCurrentArmorHitpoints = fltCurrentArmorHitpoints - fltDamageToComponent;
//}
if(fltDamageToComponent > 0)
{
float currentHitpoints = getShipComponentHitpointsCurrent(ship, primaryComponent);
float currentArmorHitpoints = getShipComponentArmorHitpointsCurrent(ship, primaryComponent);
currentArmorHitpoints = currentArmorHitpoints - fltDamageToComponent;
if(currentArmorHitpoints < 0)
{
float fltRemainingDamage = Math.abs(currentArmorHitpoints);
currentHitpoints = currentHitpoints - fltRemainingDamage;
if(currentHitpoints < 0)
{
string_id strSpam = new string_id("space/space_interaction", "droid_component_too_damaged");
string_id strComponent = new string_id("space/space_interaction", space_crafting.getShipComponentStringType(primaryComponent));
prose_package proseTest = prose.getPackage(strSpam, strComponent);
return;
}
else
{
setShipComponentArmorHitpointsCurrent(ship, primaryComponent, 0);
setShipComponentHitpointsCurrent(ship, primaryComponent, currentHitpoints);
recalculateEfficiency(primaryComponent, ship);
}
}
else
{
setShipComponentArmorHitpointsCurrent(ship, primaryComponent, currentArmorHitpoints);
// no efficiency mod since current hp arent used
}
}
}
return;
}
void vampiricTypeShipsSystemsRepair(obj_id pilot, obj_id ship, int successLevel)
{
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** just entered function with pilot ID of: "+pilot+" ship ID of: "+ship+" and successLevel of: "+successLevel);
if(!isIdValid(ship))
return;
//float[] currentDamagePercentage = new float[ship_component_type.SCT_num_types]; //comment out if we use the resizeable array approach
float highestDamagedComponentPercentage = 0.0f;
int highestDamagedComponentIndexNumber = 0;
float componentDamagePercentageSum = 0.0f;
int badComponentCounter = 0;
float highestDamagedComponentMaxPoints = 0.0f;
float totalComponentMaxHitPoints = 0.0f;
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** Completed initialization");
int[] componentSlotsTarget = space_crafting.getShipInstalledSlots(ship);
float[] currentDamagePercentage = new float[componentSlotsTarget.length]; //comment out if we use the resizeable array approach
for(int currentShipComponent = 0; currentShipComponent < componentSlotsTarget.length; currentShipComponent++)
{
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** currentShipComponent = "+currentShipComponent);
//get stats for current component
float currentHitPoints = getShipComponentHitpointsCurrent(ship, currentShipComponent);
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** currentHitPoints = "+currentHitPoints);
float maxHitPoints = getShipComponentHitpointsMaximum(ship, currentShipComponent);
if(maxHitPoints >= 1.0f)
{
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** maxHitPoints = "+maxHitPoints);
//sum the stats up so that we build a picture of overall ship component health
totalComponentMaxHitPoints += maxHitPoints;
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** totalComponentMaxHitPoints = "+totalComponentMaxHitPoints);
//figure out the damage percentage for this component so that we can see if it's the worst.
currentDamagePercentage[currentShipComponent] = (((maxHitPoints - currentHitPoints) / maxHitPoints) * 100);
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** currentDamagePercentage[currentShipComponent] = "+currentDamagePercentage[currentShipComponent]);
componentDamagePercentageSum += currentDamagePercentage[currentShipComponent]; //Add up all the percentage damages so that we can check average ship condition in a minute
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** componentDamagePercentageSum = "+componentDamagePercentageSum);
if(currentDamagePercentage[currentShipComponent] > highestDamagedComponentPercentage) //If the current component IS the worst damaged, then...
{
//Save off its vital statistics so that we can build numbers on our desired modifications... This is the component that will be affected by repairs
highestDamagedComponentPercentage = currentDamagePercentage[currentShipComponent];
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** highestDamagedComponentPercentage = "+highestDamagedComponentPercentage);
highestDamagedComponentIndexNumber = currentShipComponent;
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** highestDamagedComponentIndexNumber = "+highestDamagedComponentIndexNumber);
highestDamagedComponentMaxPoints = getShipComponentHitpointsMaximum(ship, currentShipComponent);
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** highestDamagedComponentMaxPoints = "+highestDamagedComponentMaxPoints);
}
}
else
{
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** BAD COMPONENT DETECTED - maxHitPoints = "+maxHitPoints);
badComponentCounter++;
}
}
// Now that we looked at all the components, let's see what the average would be without the worst hurt component
float averageDamagePercentageMinusMaxOne = (componentDamagePercentageSum - highestDamagedComponentPercentage) / (componentSlotsTarget.length - (badComponentCounter + 1));
// Now we need to find out how far off our worst damaged component is from the norm
float damagePercentageDelta = highestDamagedComponentPercentage - averageDamagePercentageMinusMaxOne;
if(damagePercentageDelta < 5.0f)
{
//sendSystemMessageTestingOnly(pilot, "There isn't a large enough difference between your healthy and unhealthy components to make it worth proceeding. Aborting Process.");
string_id strSpam = new string_id("space/space_interaction", "vampiric_repair_useless_abort");
sendSystemMessage(pilot, strSpam);
return;
}
// Now what does that mean in terms of actual hit points worth of damage to be re-distributed?
float damagePointDispersionPool = (damagePercentageDelta / 100.0f) * highestDamagedComponentMaxPoints;
//debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** Just completed post-mainloop initialization of averages");
//debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** Average damage percentage without the worst one is: averageDamagePercentageMinusMaxOne:"+averageDamagePercentageMinusMaxOne);
//debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** Difference between that average and the worst one is: damagePercentageDelta: "+damagePercentageDelta);
//debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** That gives us an unmodified damage point dispersion pool of: damagePointDispersionPool:"+damagePointDispersionPool);
//pull the damagePointDispersionPool points of damage out of the most heavily damaged component to prep them for dispersion
float currentHitPointAdjustment = getShipComponentHitpointsCurrent(ship, highestDamagedComponentIndexNumber) + damagePointDispersionPool; //add points back to the damaged object, as this health is 'purchased' by the pool being generated
if(currentHitPointAdjustment > highestDamagedComponentMaxPoints)
currentHitPointAdjustment = highestDamagedComponentMaxPoints;
setShipComponentHitpointsCurrent(ship, highestDamagedComponentIndexNumber, currentHitPointAdjustment);
//debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** Just set the damage level of the worst to "+currentHitPointAdjustment);
if(successLevel == 1)
damagePointDispersionPool = damagePointDispersionPool - (damagePointDispersionPool * 0.15f); // 15% damage discount for doing so well on skill check
else if(successLevel == 2)
damagePointDispersionPool = damagePointDispersionPool - (damagePointDispersionPool * 0.05f); // 5% damage discount for doing so well on skill check
else if(successLevel == 4)
damagePointDispersionPool = damagePointDispersionPool + (damagePointDispersionPool * 0.05f); // 5% damage penalty for doing missing the skill check
else if(successLevel == 6)
damagePointDispersionPool = damagePointDispersionPool + (damagePointDispersionPool * 0.20f); // 20% damage penalty for totally blowing the skill check and the fail-safe check
debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** Just resized the damagePointDispersionPool based upon successlevel of skill check.");
debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** Size of skill-modified damagePointDispersionPool is: " + damagePointDispersionPool);
// FIRE OFF THE CEF EFFECTS Loop
int damageLoops = (int) (damagePointDispersionPool / 10);
if(damageLoops > 5)
damageLoops = 5;
dictionary params = new dictionary();
params.put("damage_loops", damageLoops);
params.put("pilot", pilot);
messageTo(ship, "vRepairDamageCEFLoop", params, 3.0f, false);
for(int currentShipComponent = 0; currentShipComponent < componentSlotsTarget.length; currentShipComponent++)
{
float mmaxHitPoints = getShipComponentHitpointsMaximum(ship, currentShipComponent);
if(mmaxHitPoints >= 1.0f)
{
float percentageOfTotalComponentHitPoints = mmaxHitPoints / totalComponentMaxHitPoints;
float hitPointDelta = percentageOfTotalComponentHitPoints * damagePointDispersionPool;
float currentHitPoints = getShipComponentHitpointsCurrent(ship, currentShipComponent);
if(hitPointDelta > currentHitPoints) //if a component's share of the damage is more than it can handle, alter the amount to be taken to within 1 point of failure.
hitPointDelta = (currentHitPoints - 1);
float newHitPoints = currentHitPoints - hitPointDelta;
//debugServerConsoleMsg(null, " ********** Just modified component "+currentShipComponent+" which had "+currentHitPoints+" by "+hitPointDelta+" points to "+newHitPoints+" points");
setShipComponentHitpointsCurrent(ship, currentShipComponent, newHitPoints);
//damagePointDispersionPool -= hitPointDelta;
//debugServerConsoleMsg(null, " ********** Damage dispersion pool now has "+damagePointDispersionPool+" points left to dole out.");
}
else
{
//debugServerConsoleMsg(null, "space_combat.vamiricTypeShipsSystemsRepair ********** BAD COMPONENT DETECTED - maxHitPoints = "+mmaxHitPoints);
}
}
if(damagePointDispersionPool > 0.0f) // if there are leftover damage points (likely, due to rounding errors, etc), put them on the originally worst hit component. No lost points allowed.
{
//debugServerConsoleMsg(null, "vampiricTypeShipsSystemsRepair ********** There are "+damagePointDispersionPool+" leftover points, so we're going to disperse them now. ");
float currentHitPoints = getShipComponentHitpointsCurrent(ship, highestDamagedComponentIndexNumber);
setShipComponentHitpointsCurrent(ship, highestDamagedComponentIndexNumber, currentHitPoints - damagePointDispersionPool);
}
//sendSystemMessageTestingOnly(pilot, "Pulling parts from other systems to partially repair the your worst system");
string_id strSpam = new string_id("space/space_interaction", "vampiric_repair_underway");
sendSystemMessage(pilot, strSpam);
//if ( clientEffect != "" && clientEffect != null )
// playClientEffectObj(pilot, clientEffect, ship, targetHardpointForCefPlayback(ship));
//Recalculate efficiency for all components now that we just re-arranged hitpoint values
space_pilot_command.allPurposeShipComponentReset(ship);
successLevel--; // subtract 1 for use with switch statement, but we'll still use 1-6 everywhere else
switch (successLevel)
{
case 5: //sendSystemMessageTestingOnly(self, "Catastrophic Failure! Repairs completed, but HEAVY additional damage suffered!");
strSpam = new string_id("space/space_interaction", "vampiric_big_fail");
sendSystemMessage(pilot, strSpam);
break;
case 4:
break;
case 3: //sendSystemMessageTestingOnly(self, "Repairs completed at the cost of a small amount of additional damage.");
strSpam = new string_id("space/space_interaction", "vampiric_slight_fail");
sendSystemMessage(pilot, strSpam);
break;
case 2: //sendSystemMessageTestingOnly(self, "Repairs completed.");
strSpam = new string_id("space/space_interaction", "vampiric_success");
sendSystemMessage(pilot, strSpam);
break;
case 1: //sendSystemMessageTestingOnly(self, "Repairs completed, with good results.");
strSpam = new string_id("space/space_interaction", "vampiric_good_success");
sendSystemMessage(pilot, strSpam);
break;
case 0: //sendSystemMessageTestingOnly(self, "Repairs completed, with excellent results.");
strSpam = new string_id("space/space_interaction", "vampiric_great_success");
sendSystemMessage(pilot, strSpam);
break;
}
return;
}
//This function should check a ship for localVars pertaining to a couple of situations where we will mod the difficulty of pilotCommand skill checks.
int getShipsPilotCommandSkillCheckMods(obj_id ship)
{
int mods = 0;
int currentTime = getGameTime();
if(utils.hasLocalVar(ship, "cmd.wasDamagedSkillMod"))
{
int duration = utils.getIntLocalVar(ship, "cmd.wasDamagedSkillMod");
if(currentTime < duration)
mods += 20; //the value of one command difficulty stage
}
if(utils.hasLocalVar(ship, "cmd.firedWeaponsSkillMod"))
{
int duration = utils.getIntLocalVar(ship, "cmd.firedWeaponsSkillMod");
if(currentTime < duration)
mods += 10; //the value of half of one command difficulty stage
}
return mods;
}
int doPilotCommandSkillCheck(obj_id player, string difficultyOfCommand)
{
// Take in a string rating of the difficulty, generally indicating when a command was granted in the skill tree.
// These ratings will be: "level1command", "level2command", "level3command", "level4command", "level5command"
// This function will return a successlevel of between 1 and 6. 1,2, and 3 are success states, 4 is a small failure
// 5 is a major failure with a second 50-50 chance check and if that is blown, you get the mega-failure of 6.
// I'd presume that a six means that I'm going to do bad things to you as a result.
debugServerConsoleMsg(null, "=========================================================");
debugServerConsoleMsg(null, "SPACE_COMBAT.doPilotCommandSkillCheck ============= ENTERED FUNCTION ");
debugServerConsoleMsg(null, "passed in player obj_id of: " + player + " and passed in difficulty of command of: " + difficultyOfCommand);
int risk = 0;
if(difficultyOfCommand == "level1command")
risk = 20;
else if(difficultyOfCommand == "level2command")
risk = 40;
else if(difficultyOfCommand == "level3command")
risk = 60;
else if(difficultyOfCommand == "level4command")
risk = 80;
else if(difficultyOfCommand == "level5command")
risk = 100;
else
risk = 60; //couldn't find the correct difficulty, so using a mid-level rating.
debugServerConsoleMsg(null, "Risk is computed as being " + risk);
int playerSkill = getEnhancedSkillStatisticModifier(player, "pilot_special_tactics");
debugServerConsoleMsg(null, "Player skill is " + playerSkill);
int shipMods = 0;
obj_id ship = space_transition.getContainingShip(player); // if the player doing the command is on a ship, let's check the ship for skillcheck-applicable mods
if(isIdValid(ship))
shipMods = getShipsPilotCommandSkillCheckMods(ship);
debugServerConsoleMsg(null, "shipMods came back as " + shipMods);
float dieRoll = rand(1f, 100f);
float moddedRoll = dieRoll + (float) (risk) + (float) (shipMods) - (float) (playerSkill); //you want to get UNDER the AVERAGE_COMMAND_SUCCESS_RATE. Bad mods raise the die roll, good mods lower it. A LOW roll is best.
debugServerConsoleMsg(null, "moddedRoll came back as " + moddedRoll);
// a good success is beating the target by 30%
float goodSuccess = AVERAGE_COMMAND_SUCCESS_RATE - (AVERAGE_COMMAND_SUCCESS_RATE * 0.25f);
// a great success is beating the target by 45%
float greatSuccess = AVERAGE_COMMAND_SUCCESS_RATE - (AVERAGE_COMMAND_SUCCESS_RATE * 0.50f);
// a moderate failure is missing the target by 20%
float moderateFailure = AVERAGE_COMMAND_SUCCESS_RATE + (AVERAGE_COMMAND_SUCCESS_RATE * 0.20f);
// a big failure is missing the target by 30%
float bigFailure = AVERAGE_COMMAND_SUCCESS_RATE + (AVERAGE_COMMAND_SUCCESS_RATE * 0.40f);
int successLevel = 0;
if(moddedRoll < greatSuccess)
successLevel = 1;
else if(moddedRoll < goodSuccess)
successLevel = 2;
else if(moddedRoll < AVERAGE_COMMAND_SUCCESS_RATE)
successLevel = 3;
else if(moddedRoll < moderateFailure)
successLevel = 4;
else // you blew it. Let's see how bad. Generally success level 5 will only be an abort. Success level 6 will mean bad, bad things.
if(rand(1f, 100f) < 50f)
successLevel = 5;
else
successLevel = 6;
debugServerConsoleMsg(null, "returning a success level of " + successLevel);
return successLevel;
}
boolean readyForBomberStrike(obj_id ship, obj_id commander)
{
debugServerConsoleMsg(null, "space_combat - readyForBomberStrike");
if(utils.hasLocalVar(commander, "cmd.bmb.bmbrStrike"))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "You've already called in a strike team and Command won't release an additional force to you.");
string_id strSpam = new string_id("space/space_interaction", "already_bmbr_strike");
sendSystemMessage(commander, strSpam);
return false;
}
if(isShipComponentDisabled(ship, ship_chassis_slot_type.SCST_reactor))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Your ship's systems are currently disabled. Unable to access communications to send strike package request.");
string_id strSpam = new string_id("space/space_interaction", "systems_disabled_strike_pack");
sendSystemMessage(commander, strSpam);
return false;
}
//CHECK THE PLAYERS IN THE AREA TO SEE HOW MANY HAVE CALLED BOMBERSTRIKES.
//THE THINK WE ARE KEYING OFF OF IS QUITE TRANSITORY, SO I'M NOT GOING TO SWEAT IT TOO MUCH
int localCalledBomberCount = 0;
obj_id[] nearbyPlayers = getObservedPlayerShips(ship, true);
for(int i = 0; i < nearbyPlayers.length; i++)
{
if(isIdValid(nearbyPlayers[i]))
{
if(utils.hasLocalVar(nearbyPlayers[i], "cmd.bmb.bmbrStrike"))
localCalledBomberCount++;
}
}
if(localCalledBomberCount > 9)
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "There are no strike assets currently available to fulfill your support request.");
string_id strSpam = new string_id("space/space_interaction", "bomberstrike_none_available");
sendSystemMessage(commander, strSpam);
return false;
}
obj_id target = getLookAtTarget(ship);
if(!isIdValid(target))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Fleet Operations will not allocate craft to attack that target.");
string_id strSpam = new string_id("space/space_pilot_command", "bomberstrike_not_at_player");
sendSystemMessage(commander, strSpam);
return false;
}
//if ( pvpIsEnemy(ship, target) && pvpCanAttack(ship, target))
if(space_utils.isPlayerControlledShip(target) || hasObjVar(target, "intInvincible") || space_pilot_command.isStation(target))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Fleet Operations will not allocate craft to attack that target.");
string_id strSpam = new string_id("space/space_pilot_command", "bomberstrike_not_at_player");
sendSystemMessage(commander, strSpam);
return false;
}
else if(pvpCanAttack(ship, target))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Transmitted target I.D. to Command.");
string_id strSpam = new string_id("space/space_interaction", "calling_bomberstrike");
sendSystemMessage(commander, strSpam);
return true;
}
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Transmitted target I.D. does not match a known enemy vessel configuration.");
//sendSystemMessageTestingOnly(commander, "Request for bomber Strike Package denied.");
string_id strSpam = new string_id("space/space_interaction", "bomber_not_enemy_1");
string_id strSpam2 = new string_id("space/space_interaction", "bomber_not_enemy_2");
sendSystemMessage(commander, strSpam);
sendSystemMessage(commander, strSpam2);
return false;
}
boolean executeLightBomberStrike(obj_id ship, obj_id commander, obj_id target, int CMD_LIGHT_STRIKE_DELAY)
{
debugServerConsoleMsg(null, "space_combat.executeLightBomberStrike ***** Entered Function");
int skillCheck = doPilotCommandSkillCheck(commander, "level3command");
if(skillCheck > 4)
{
string_id strSpam = new string_id("space/space_interaction", "bomberstrike_bad_skillcheck");
sendSystemMessage(commander, strSpam);
strSpam = new string_id("space/space_interaction", "bomberstrike_none_available");
sendSystemMessage(commander, strSpam);
initializeCommandTimer(commander, CMD_LIGHT_STRIKE_DELAY);
return false;
}
string packageType = "light";
//string attackType = "single";
string attackType = "many";
//call bomber
if(!space_combat.spawnStrikeBombers(ship, commander, packageType, attackType, target))
{
debugServerConsoleMsg(null, "space_combat.executeLightBomberStrike ***** This script has created a FATAL ERROR! Couldn't spawn for some reason.");
return false;
}
playClientEffectObj(commander, "clienteffect/space_command/sys_comm_imperial.cef", ship, "");
space_combat.flightDroidVocalize(ship, 1);
utils.setLocalVar(ship, "cmd.bmb.bmbrStrike", 1);
initializeCommandTimer(commander, CMD_LIGHT_STRIKE_DELAY);
//string clientEffect = null;
//string primaryComponent = null;
//emergencyCmdDamageToShipsSystems(self, ship, clientEffect, primaryComponent);
string cefPlayBackHardpoint = space_combat.targetHardpointForCefPlayback(ship);
playClientEffectObj(commander, "clienteffect/space_command/emergency_power_on.cef", ship, cefPlayBackHardpoint); //PLAY SOME COOL RADIO EFFECT HERE
return true;
}
boolean executeMediumBomberStrike(obj_id ship, obj_id commander, obj_id target, int CMD_LIGHT_STRIKE_DELAY)
{
int skillCheck = doPilotCommandSkillCheck(commander, "level4command");
if(skillCheck > 4)
{
string_id strSpam = new string_id("space/space_interaction", "bomberstrike_bad_skillcheck");
sendSystemMessage(commander, strSpam);
strSpam = new string_id("space/space_interaction", "bomberstrike_none_available");
sendSystemMessage(commander, strSpam);
initializeCommandTimer(commander, CMD_LIGHT_STRIKE_DELAY);
return false;
}
string packageType = "medium";
//string attackType = "single";
string attackType = "many";
//call bombers
if(!space_combat.spawnStrikeBombers(ship, commander, packageType, attackType, target))
{
debugServerConsoleMsg(null, "space_combat.executeMediumBomberStrike ***** This script has created a FATAL ERROR! Couldn't spawn for some reason.");
return false;
}
playClientEffectObj(commander, "clienteffect/space_command/sys_comm_imperial.cef", ship, "");
space_combat.flightDroidVocalize(ship, 1);
utils.setLocalVar(ship, "cmd.bmb.bmbrStrike", 2);
initializeCommandTimer(commander, CMD_LIGHT_STRIKE_DELAY);
//string clientEffect = null;
//string primaryComponent = null;
//emergencyCmdDamageToShipsSystems(self, ship, clientEffect, primaryComponent);
string cefPlayBackHardpoint = space_combat.targetHardpointForCefPlayback(ship);
playClientEffectObj(commander, "clienteffect/space_command/emergency_power_on.cef", ship, cefPlayBackHardpoint); //PLAY SOME COOL RADIO EFFECT HERE
return true;
}
boolean executeHeavyBomberStrike(obj_id ship, obj_id commander, obj_id target, int CMD_LIGHT_STRIKE_DELAY)
{
int skillCheck = doPilotCommandSkillCheck(commander, "level5command");
if(skillCheck > 4)
{
string_id strSpam = new string_id("space/space_interaction", "bomberstrike_bad_skillcheck");
sendSystemMessage(commander, strSpam);
strSpam = new string_id("space/space_interaction", "bomberstrike_none_available");
sendSystemMessage(commander, strSpam);
initializeCommandTimer(commander, CMD_LIGHT_STRIKE_DELAY);
return false;
}
string packageType = "heavy";
//string attackType = "single";
string attackType = "many";
//call bombers
if(!space_combat.spawnStrikeBombers(ship, commander, packageType, attackType, target))
{
debugServerConsoleMsg(null, "space_combat.executeHeavyBomberStrike ***** This script has created a FATAL ERROR! Couldn't spawn for some reason.");
return false;
}
playClientEffectObj(commander, "clienteffect/space_command/sys_comm_imperial.cef", ship, "");
space_combat.flightDroidVocalize(ship, 1);
utils.setLocalVar(ship, "cmd.bmb.bmbrStrike", 3);
initializeCommandTimer(commander, CMD_LIGHT_STRIKE_DELAY);
//string clientEffect = null;
//string primaryComponent = null;
//emergencyCmdDamageToShipsSystems(self, ship, clientEffect, primaryComponent);
string cefPlayBackHardpoint = space_combat.targetHardpointForCefPlayback(ship);
playClientEffectObj(commander, "clienteffect/space_command/emergency_power_on.cef", ship, cefPlayBackHardpoint); //PLAY SOME COOL RADIO EFFECT HERE
return true;
}
transform playerCommandSpawnerLocGetter(obj_id ship, boolean flip)
{
debugServerConsoleMsg(null, "PLAYERcOMMANDsPAWNERlOCgETTER");
//FOR GOD'S SAKE, IF YOU ARE GOING TO USE THE TARGET OBJ_ID THAT'S PASSED IN, DO A FRIGGIN' NULL-CHECK FIRST!!!!!!!
// I am intentionally passing in null in a place or two, but am not using the obj_id 'target' at this time, so no harm, no foul.
//get player's current location
transform loc = getTransform_o2w(ship);
// Move the spawner starting spot out in front of us.
float dist = rand(600.f, 700.f);
vector n = loc.getLocalFrameK_p().normalize().multiply(dist); // Project a point out in front of us.
loc = loc.move_p(n);
if(flip == true)
loc = loc.yaw_l(3.14f); // Flip the spawner starting spot around so its facing us.
// Find a spot on the IJ plane for deviation in a cone shape.
vector vi = loc.getLocalFrameI_p().normalize().multiply(rand(-150.f, 150.f));
vector vj = loc.getLocalFrameJ_p().normalize().multiply(rand(-150.f, 150.f));
vector vd = vi.add(vj);
loc = loc.move_p(vd);
return loc;
}
boolean spawnStrikeBombers(obj_id ship, obj_id commander, string packageType, string attack_type, obj_id target)
{
debugServerConsoleMsg(null, "space_combat.spawnStrikeBombers ***** Entered Function");
if(!isIdValid(ship) || !isIdValid(commander) || !isIdValid(target))
return false;
transform loc = playerCommandSpawnerLocGetter(ship, true);
string targetDifficultyTier = "_tier3";
int targetSquad = ship_ai.unitGetSquadId(target);
int targetSquadSize = ship_ai.squadGetSize(targetSquad);
targetDifficultyTier = "_tier" + space_pilot_command.targetTierDetect(target);
string strikePackageType = "squad_plyr_cmd_bmbr_basic" + targetDifficultyTier;
if(packageType == "medium")
strikePackageType = "squad_plyr_cmd_bmbr_advanced" + targetDifficultyTier;
else if(packageType == "heavy")
strikePackageType = "squad_plyr_cmd_bmbr_extreme" + targetDifficultyTier;
resizeable obj_id[] objStrikePack = space_create.createSquadHyperspace(null, strikePackageType, loc, 20.0f, null);
if(!isIdValid(objStrikePack[0])) // if the lead ship in the squad is invalid, this is all for naught.
return false;
//Get references for new strike pakage
int bomberSquadId = ship_ai.unitGetSquadId(objStrikePack[0]);
obj_id[] squaddyList = null;
if(ship_ai.isSquadIdValid(bomberSquadId))
squaddyList = ship_ai.squadGetUnitList(bomberSquadId);
else
return false;
if(objStrikePack.length > 1)
ship_ai.squadSetFormationSpacing(bomberSquadId, 3.0f); //space out the bombers
//connect bombers to player. Tell bombers where to send death messages, and Store initial strike package squad ID on player
for(int i = 0; i < squaddyList.length; i++)
{
setObjVar(squaddyList[i], "commanderPlayer", commander);
}
if(utils.hasLocalVar(commander, "cmd.bmb.bmbrSquadId"))
utils.removeLocalVar(commander, "cmd.bmb.bmbrSquadId");
utils.setLocalVar(commander, "cmd.bmb.bmbrSquadId", bomberSquadId);
if(utils.hasLocalVar(commander, "cmd.bmb.initialStrikePackSize"))
utils.removeLocalVar(commander, "cmd.bmb.initialStrikePackSize");
utils.setLocalVar(commander, "cmd.bmb.initialStrikePackSize", objStrikePack.length);
utils.setLocalVar(commander, "cmd.bmb.currentStrikePackSize", objStrikePack.length);
transform targetLoc = getTransform_o2w(target);
transform[]loiterPath = ship_ai.createPatrolPathLoiter(targetLoc, 100.0f, 100.0f); //Set up loiter area
ship_ai.squadPatrol(bomberSquadId, loiterPath); //Set up loiter area
//ship_ai.squadLoiter(bomberSquadId, targetLoc, 25.0f, 75.0f); //replacing this loiter technique with Dan's suggested createPatrolPathLoiter/squadPatrol methods
//Target the bombers against whatever the player wants blown up.
if(attack_type == "single")
{
ship_ai.squadAddTarget(bomberSquadId, target); // if the spawner says attack a single, then attack just the singular target
}
else
{
ship_ai.squadAddTarget(bomberSquadId, targetSquad); // if the spawner says attack a group, then attack the whole enemy target squad
}
initializeTargetTracking(commander, bomberSquadId, targetSquad); //Setup the stuff so that when the targets are destroyed, the bomber strike package evacuates.
//Tell the player that his bombers have arrived
string_id sid = new string_id("space/space_interaction", "bombers_arriving");
prose_package pp = new prose_package();
pp.stringId = sid;
commPlayers(squaddyList[0], null, null, 6.0f, commander, pp);
//Spawn the escorts for the bombers -- //NEGATIVE - THIS IS NOT THE WAY I'M DOING IT ANYMORE. NOW THE FIGHTERS ARE PART OF THE BOMBERSQUAD
//setupStrikePackageEscort(bomberSquadId, packageType, commander, targetDifficultyTier);
return true;
}
boolean setupStrikePackageEscort(int bomberSquadId, string packageType, obj_id commander, string targetDifficultyTier)
{
debugServerConsoleMsg(null, "SETUPsTRIKEpACKAGEeSCORT");
obj_id[] bomberSquaddyList = null;
if(ship_ai.isSquadIdValid(bomberSquadId))
bomberSquaddyList = ship_ai.squadGetUnitList(bomberSquadId);
else
return false;
int numBombers = ship_ai.squadGetSize(bomberSquadId);
int successLevel = doPilotCommandSkillCheck(commander, "level3command");
string escortPackageType = "";
debugServerConsoleMsg(null, "============================================");
debugServerConsoleMsg(null, "SPACE_COMBAT.SETUPsTRIKEpACKAGEeSCORT = successLevel came back as: " + successLevel);
switch (successLevel)
{
case 6:
escortPackageType = "squad_plyr_cmd_bmbr_escort_basic" + targetDifficultyTier;
break;
case 5:
escortPackageType = "squad_plyr_cmd_bmbr_escort_basic" + targetDifficultyTier;
break;
case 4:
escortPackageType = "squad_plyr_cmd_bmbr_escort_basic" + targetDifficultyTier;
break;
case 3:
escortPackageType = "squad_plyr_cmd_bmbr_escort_interceptor" + targetDifficultyTier;
break;
case 2:
escortPackageType = "squad_plyr_cmd_bmbr_escort_interceptor" + targetDifficultyTier;
break;
case 1:
escortPackageType = "squad_plyr_cmd_bmbr_escort_advanced" + targetDifficultyTier;
break;
case 0:
escortPackageType = "squad_plyr_cmd_bmbr_escort_advanced" + targetDifficultyTier;
break;
}
//transform loc = getTransform_o2w(bomberSquaddyList[0]); Old and incorrect location grabber
transform loc = playerCommandSpawnerLocGetter(bomberSquaddyList[0], false);
int totalEscorts = 0;
for(int i = 0; i < bomberSquaddyList.length; i++)
{
resizeable obj_id[] objStrikeEscortPack = space_create.createSquadHyperspace(null, escortPackageType, loc, 20.0f, null);
//Get references for new strike package
int escortSquadId = ship_ai.unitGetSquadId(objStrikeEscortPack[0]);
obj_id[] escortSquaddyList = null;
if(ship_ai.isSquadIdValid(escortSquadId))
escortSquaddyList = ship_ai.squadGetUnitList(escortSquadId);
else
return false;
totalEscorts += objStrikeEscortPack.length;
utils.setLocalVar(bomberSquaddyList[i], "escortSquadId", escortSquadId);
utils.setLocalVar(bomberSquaddyList[i], "crrntEscrtSqdSz", escortSquaddyList.length);
//connect fighters to player. Tell fighters where to send death messages, and store initial escort package squad IDs on player
for(int j = 0; j < escortSquaddyList.length; j++)
{
setObjVar(escortSquaddyList[j], "commanderPlayer", commander);
}
if(utils.hasLocalVar(commander, "cmd.bmb.initEscrtPckSize"))
utils.removeLocalVar(commander, "cmd.bmb.initEscrtPckSize");
utils.setLocalVar(commander, "cmd.bmb.initEscrtPckSize", totalEscorts);
//HAVE THE ESCORTS FOLLOW THE BOMBERS AROUND, TILL WE GET ESCORT COMMAND
ship_ai.squadFollow(escortSquadId, bomberSquaddyList[i], new vector(0.0f, 0.0f, -1.0f), 2.0f);
ship_ai.squadSetGuardTarget(escortSquadId, bomberSquadId);
}
return true;
}
void strikePackageEvac(obj_id commander, int bomberSquadId, int fighterSquadId)
{
debugServerConsoleMsg(null, "STRIKEpACKAGEeVAC");
//clean up the player's localVars
utils.removeLocalVar(commander, "cmd.bmb");
obj_id ship = space_transition.getContainingShip(commander); // THIS LINE MIGHT BE A PROBLEM IF THE REASON WE'RE EVAC'ING THE STRIKE PACKAGE IS BECAUSE THE PLAYER ////LOGGED ON US.
// MIGHT NEED TO GET AN EVAC LOCATION FOR THE BOMBERS TO HEAD TO WITHOUT THE PLAYER.
obj_id strikeLeader = null;
int strikeSurvivorSquad = -1;
//Are there any bombers left to evacuate?
int currentStrikePackageSize = utils.getIntLocalVar(commander, "cmd.bmb.currentStrikePackSize");
if(bomberSquadId > 0 && fighterSquadId < 0) // there are bombers left, so they'll control the evac
{
obj_id[] bomberSquaddyList = null;
if(ship_ai.isSquadIdValid(bomberSquadId))
bomberSquaddyList = ship_ai.squadGetUnitList(bomberSquadId);
else
return;
if(hasObjVar(bomberSquaddyList[0], "evacuate")) //check to see if the bombers are already evacuating. Abort the rest of this function if they are.
return;
//Set an evacuate objvar on all bombers and escort fighters to let them know to ignore the next onDestroy trigger... it's probably them hyperspacing out!
for(int i = 0; i < bomberSquaddyList.length; i++)
{
setObjVar(bomberSquaddyList[i], "evacuate", 1);
/* NO MORE ANY SUCH THING AS A SEPARATE SQUAD OF ESCORTS. THEY'RE BUILT INTO THE BOMBER SQUAD NOW
int oldEscortUnitCount = utils.getIntLocalVar(bomberSquaddyList[i], "crrntEscrtSqdSz");
if ( oldEscortUnitCount > 0 )
{
int escortSquadId = utils.getIntLocalVar(bomberSquaddyList[i], "escortSquadId");
obj_id[] escortSquaddyList = ship_ai.squadGetUnitList(escortSquadId);
for(int j = 0; j<escortSquaddyList.length; j++)
{
setObjVar(escortSquaddyList[j],"evacuate", 1 );
}
}
*/
}
strikeLeader = bomberSquaddyList[0];
strikeSurvivorSquad = bomberSquadId;
}
/* NO MORE ANY SUCH THING AS A SEPARATE SQUAD OF ESCORTS. THEY'RE BUILT INTO THE BOMBER SQUAD NOW
else // no bombers left, so the fighters will evac on their own
{
obj_id[] fighterSquaddyList = ship_ai.squadGetUnitList(fighterSquadId);
if ( hasObjVar(fighterSquaddyList[0],"evacuate" )) //check to see if the bombers are already evacuating. Abort the rest of this function if they are.
return;
//Set an evacuate objvar on all bombers and escort fighters to let them know to ignore the next onDestroy trigger... it's probably them hyperspacing out!
for(int i = 0; i<fighterSquaddyList.length; i++)
{
setObjVar(fighterSquaddyList[i],"evacuate", 1 );
}
strikeLeader = fighterSquaddyList[0];
strikeSurvivorSquad = fighterSquadId;
}
*/
//issue evacuation-related ai commands to the strikeForce.
obj_id squadTarget = ship_ai.unitGetPrimaryAttackTarget(strikeLeader);
if(!isIdValid(ship))
ship = strikeLeader; //if the player doesn't exist any more, use the strike leader to determine an evac location
transform loc = space_combat.playerCommandSpawnerLocGetter(ship, true);
ship_ai.squadSetAttackOrders(strikeSurvivorSquad, ship_ai.ATTACK_ORDERS_HOLD_FIRE);
ship_ai.squadMoveTo(strikeSurvivorSquad, loc);
//nothing here for escort instructions, as they should automagically be following the bombers around.
//Tell the player that the strike force is bugging out
string_id sid = new string_id("space/space_interaction", "strikeforce_withdrawing");
prose_package pp = new prose_package();
pp.stringId = sid;
commPlayers(strikeLeader, null, null, 6.0f, commander, pp);
//clean up the scripts and objvars off of the targets, if any are still alive
if(utils.hasLocalVar(commander, "cmd.bmb.targetSquadId") && !utils.hasLocalVar(commander, "cmd.bmb.targetSquadCrrntSz"))
{
int targetSquadId = utils.getIntLocalVar(commander, "cmd.bmb.targetSquadId");
obj_id[] targetSquaddyList = null;
if(ship_ai.isSquadIdValid(targetSquadId))
targetSquaddyList = ship_ai.squadGetUnitList(targetSquadId);
else
return;
for(int i = 0; i < targetSquaddyList.length; i++)
{
if(hasScript(targetSquaddyList[i], "space.command.player_cmd_bomber_strike_target"))
detachScript(targetSquaddyList[i], "space.command.player_cmd_bomber_strike_target");
if(hasObjVar(targetSquaddyList[i], "targetedByPlayerObjId"))
removeObjVar(targetSquaddyList[i], "targetedByPlayerObjId");
if(hasObjVar(targetSquaddyList[i], "damageMultiplier"))
removeObjVar(targetSquaddyList[i], "damageMultiplier");
}
}
return;
}
void initializeTargetTracking(obj_id commander, int bomberSquadId, int targetSquadId)
{
if(utils.hasLocalVar(commander, "cmd.bmb.targetSquadId"))
utils.removeLocalVar(commander, "cmd.bmb.targetSquadId");
obj_id[] targetSquaddyList = null;
if(ship_ai.isSquadIdValid(targetSquadId))
targetSquaddyList = ship_ai.squadGetUnitList(targetSquadId);
else
return;
//initialize the player to track the targets
utils.setLocalVar(commander, "cmd.bmb.targetSquadId", targetSquadId);
utils.setLocalVar(commander, "cmd.bmb.targetSquadCrrntSz", targetSquaddyList.length);
//initialize the targets to alert the player object when they are wasted
for(int i = 0; i < targetSquaddyList.length; i++)
{
attachScript(targetSquaddyList[i], "space.command.player_cmd_bomber_strike_target");
setObjVar(targetSquaddyList[i], "targetedByPlayerObjId", commander);
setObjVar(targetSquaddyList[i], "damageMultiplier", NPC_DAMAGE_MULTIPLIER);
}
return;
}
void strikeBomberCleanup(obj_id commander)
{
if(utils.hasLocalVar(commander, "cmd.bmb.bmbrSquadId"))
{
int bomberSquadId = utils.getIntLocalVar(commander, "cmd.bmb.bmbrSquadId");
if(ship_ai.isSquadIdValid(bomberSquadId))
strikePackageEvac(commander, bomberSquadId, -1);
}
return;
}
boolean readyForPirateRaid(obj_id ship, obj_id commander)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.readyForPirateRaid");
if(utils.hasLocalVar(ship, "cmd.pirate.goRaid"))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "All the pirates willing to come to your aid are already assisting.");
string_id strSpam = new string_id("space/space_interaction", "already_pirate_raid");
sendSystemMessage(commander, strSpam);
return false;
}
if(isShipComponentDisabled(ship, ship_chassis_slot_type.SCST_reactor))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Your ship's systems are currently disabled. Unable to access communications to send call for assistance.");
string_id strSpam = new string_id("space/space_interaction", "systems_disabled_pirate_raid");
sendSystemMessage(commander, strSpam);
return false;
}
//CHECK THE PLAYERS IN THE AREA TO SEE HOW MANY HAVE CALLED PIRATERAIDS.
//THE THINK WE ARE KEYING OFF OF IS QUITE TRANSITORY, SO I'M NOT GOING TO SWEAT IT TOO MUCH
int localCalledPirateCount = 0;
obj_id[] nearbyPlayers = getObservedPlayerShips(ship, true);
for(int i = 0; i < nearbyPlayers.length; i++)
{
if(isIdValid(nearbyPlayers[i]))
{
if(utils.hasLocalVar(nearbyPlayers[i], "cmd.pirate.goRaid"))
localCalledPirateCount++;
}
}
if(localCalledPirateCount > 4)
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "There don't appear to be any pirates paying attention locally.");
string_id strSpam = new string_id("space/space_pilot_command", "pirateraid_none_available");
sendSystemMessage(commander, strSpam);
return false;
}
obj_id target = getLookAtTarget(ship);
if(isIdValid(target))
{
if(!space_pilot_command.isStation(target))
{
if(space_utils.isShip(target))
{
if(pvpCanAttack(ship, target))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Transmitted call for assistance on commonly-used pirate frequencies.");
string_id strSpam = new string_id("space/space_interaction", "calling_pirate_raid");
sendSystemMessage(commander, strSpam);
return true;
}
}
}
}
else if(!isIdValid(target))
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "Transmitted call for assistance on commonly-used pirate frequencies.");
string_id strSpam = new string_id("space/space_interaction", "calling_pirate_raid");
sendSystemMessage(commander, strSpam);
return true;
}
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "You'll never be able to talk the pirates into attacking THAT.");
string_id strSpam = new string_id("space/space_interaction", "pirate_raid_not_enemy");
sendSystemMessage(commander, strSpam);
return false;
}
boolean executePirateRaidOne(obj_id ship, obj_id commander, obj_id target, int CMD_PIRATE_LURE_DELAY)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.executePirateRaidOne");
string packageType = "light";
//string attackType = "single";
string attackType = "many";
string level = "level1";
//call pirates
if(!space_combat.spawnPirateRaiders(ship, commander, level, attackType, target))
{
string_id strSpam = new string_id("space/space_interaction", "pirate_raid_systems_not_ready");
sendSystemMessage(commander, strSpam);
debugServerConsoleMsg(null, "space_combat.executePirateRaidone ***** script has created a FATAL ERROR! Could not spawn for some reason");
return false;
}
playClientEffectObj(commander, "clienteffect/space_command/sys_comm_generic.cef", ship, "");
space_combat.flightDroidVocalize(ship, 1);
utils.setLocalVar(ship, "cmd.pirate.goRaid", 1);
initializeCommandTimer(commander, CMD_PIRATE_LURE_DELAY);
//string clientEffect = null;
//string primaryComponent = null;
//emergencyCmdDamageToShipsSystems(self, ship, clientEffect, primaryComponent);
string cefPlayBackHardpoint = space_combat.targetHardpointForCefPlayback(ship);
playClientEffectObj(commander, "clienteffect/space_command/emergency_power_on.cef", ship, cefPlayBackHardpoint); //PLAY SOME COOL RADIO EFFECT HERE
return true;
}
boolean executePirateRaidTwo(obj_id ship, obj_id commander, obj_id target, int CMD_PIRATE_LURE_DELAY)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.executePirateRaidOne");
string packageType = "light";
//string attackType = "single";
string attackType = "many";
string level = "level2";
//call pirates
if(!space_combat.spawnPirateRaiders(ship, commander, level, attackType, target))
{
string_id strSpam = new string_id("space/space_interaction", "pirate_raid_systems_not_ready");
sendSystemMessage(commander, strSpam);
debugServerConsoleMsg(null, "space_combat.executePirateRaidTwo ***** script has created a FATAL ERROR! Could not spawn for some reason");
return false;
}
playClientEffectObj(commander, "clienteffect/space_command/sys_comm_generic.cef", ship, "");
space_combat.flightDroidVocalize(ship, 1);
utils.setLocalVar(ship, "cmd.pirate.goRaid", 2);
initializeCommandTimer(commander, CMD_PIRATE_LURE_DELAY);
//string clientEffect = null;
//string primaryComponent = null;
//emergencyCmdDamageToShipsSystems(self, ship, clientEffect, primaryComponent);
string cefPlayBackHardpoint = space_combat.targetHardpointForCefPlayback(ship);
playClientEffectObj(commander, "clienteffect/space_command/emergency_power_on.cef", ship, cefPlayBackHardpoint); //PLAY SOME COOL RADIO EFFECT HERE
return true;
}
boolean spawnPirateRaiders(obj_id ship, obj_id commander, string level, string attack_type, obj_id target)
{
debugServerConsoleMsg(null, "SPACE_COMBAT.spawnPirateRaiders");
if(!isIdValid(ship) || !isIdValid(commander))
return false;
if(!isIdValid(target)) // Okay...this condition reads if target is not valid and target is valid...so the code below this condition is never reached
{
debugServerConsoleMsg(null, "SPACE_COMBAT.spawnPirateRaiders -- Skipping spawning stuff. Target was invalid and wasn't null");
return false;
}
transform loc = playerCommandSpawnerLocGetter(ship, true);
//init default values
int pirateForceMaxSize = 1;
string pirateForceGear = PIRATE_EQUIPMENT_D;
int successLevel = 4;
if(level == "level1") // operations for if this is the less powerful version of the command.
{
successLevel = doPilotCommandSkillCheck(commander, "level2command");
debugServerConsoleMsg(null, "============================================");
debugServerConsoleMsg(null, "SPACE_COMBAT.spawnPirateRaiders = successLevel came back as: " + successLevel);
switch (successLevel)
{
case 6:
pirateForceMaxSize = 3;
pirateForceGear = PIRATE_EQUIPMENT_B;
break;
case 5:
pirateForceMaxSize = 0;
break;
case 4:
pirateForceMaxSize = 2;
pirateForceGear = PIRATE_EQUIPMENT_D;
break;
case 3:
pirateForceMaxSize = 4;
pirateForceGear = PIRATE_EQUIPMENT_C;
break;
case 2:
pirateForceMaxSize = 4;
pirateForceGear = PIRATE_EQUIPMENT_C;
break;
case 1:
pirateForceMaxSize = 4;
pirateForceGear = PIRATE_EQUIPMENT_B;
break;
case 0:
pirateForceMaxSize = 6;
pirateForceGear = PIRATE_EQUIPMENT_B;
break;
}
if(successLevel == 5) //if the player blew their roll, no effect.
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "There are no pirates within navigation distance that are willing to come to your aid.");
string_id strSpam = new string_id("space/space_interaction", "none_around_pirate_raid");
sendSystemMessage(commander, strSpam);
return false;
}
}
else if(level == "level2") // operations for if this is the more powerful version of the command.
{
successLevel = doPilotCommandSkillCheck(commander, "level4command");
debugServerConsoleMsg(null, "============================================");
debugServerConsoleMsg(null, "SPACE_COMBAT.spawnPirateRaiders = successLevel came back as: " + successLevel);
switch (successLevel)
{
case 6:
pirateForceMaxSize = 3;
pirateForceGear = PIRATE_EQUIPMENT_A;
break;
case 5:
pirateForceMaxSize = 0;
break;
case 4:
pirateForceMaxSize = 2;
pirateForceGear = PIRATE_EQUIPMENT_C;
break;
case 3:
pirateForceMaxSize = 4;
pirateForceGear = PIRATE_EQUIPMENT_B;
break;
case 2:
pirateForceMaxSize = 4;
pirateForceGear = PIRATE_EQUIPMENT_A;
break;
case 1:
pirateForceMaxSize = 4;
pirateForceGear = PIRATE_EQUIPMENT_A;
break;
case 0:
pirateForceMaxSize = 6;
pirateForceGear = PIRATE_EQUIPMENT_AA;
break;
}
if(successLevel == 5) //if the player blew their roll, no effect.
{
//LOCALIZE THIS
//sendSystemMessageTestingOnly(commander, "There are no pirates within navigation distance that are willing to come to your aid.");
string_id strSpam = new string_id("space/space_interaction", "none_around_pirate_raid");
sendSystemMessage(commander, strSpam);
return false;
}
else if(successLevel < 4)
ship_ai.unitSetAutoAggroImmuneTime(ship, 60.0f); //MAKE IT SO NOTHING NEW WILL ATTACK YOU FOR A BIT FOLLOWING THE SUCCESSFUL USE OF THE COMMAND TO SPAWN PIRATES.
}
string[] possibleShips = dataTableGetStringColumnNoDefaults(PIRATE_EQUIPMENT_DATATABLE, pirateForceGear);
string leadPirate = possibleShips[(int) (rand(0, possibleShips.length - 1))];
debugServerConsoleMsg(null, "SPACE_COMBAT.spawnPirateRaiders ------------ leadPirate chosen was: " + leadPirate);
obj_id pirateLeader = space_create.createShipHyperspace(leadPirate, loc, null);
if(!isIdValid(pirateLeader)) // if the lead ship in the squad is invalid, this is all for naught.
return false;
int pirateSquadId = ship_ai.unitGetSquadId(pirateLeader);
int pirateForceSize = (int) (rand(1, pirateForceMaxSize - 1));
for(int i = 0; i < pirateForceSize; i++)
{
string spawnShip = possibleShips[(int) (rand(0, possibleShips.length - 1))];
debugServerConsoleMsg(null, "SPACE_COMBAT.spawnPirateRaiders ------------ secondary pirate chosen was: " + spawnShip);
loc = playerCommandSpawnerLocGetter(ship, true);
obj_id currentPirate = space_create.createShipHyperspace(spawnShip, loc, null);
ship_ai.unitSetSquadId(currentPirate, pirateSquadId);
}
//Get references for new strike pakage
obj_id[] squaddyList = null;
if(ship_ai.isSquadIdValid(pirateSquadId))
squaddyList = ship_ai.squadGetUnitList(pirateSquadId);
else
return false;
pirateForceSize = ship_ai.squadGetSize(pirateSquadId);
if(squaddyList.length > 1)
ship_ai.squadSetFormationSpacing(pirateSquadId, 3.0f); //space out the bombers
//connect pirates to bouy. Tell pirates where to send death messages, and Store initial strike package squad ID on bouy
for(int i = 0; i < squaddyList.length; i++)
{
setObjVar(squaddyList[i], "commanderPlayer", commander);
attachScript(squaddyList[i], "space.command.player_cmd_pirate");
}
if(utils.hasLocalVar(commander, "cmd.pirate.squadId"))
utils.removeLocalVar(commander, "cmd.pirate.squadId");
utils.setLocalVar(commander, "cmd.pirate.squadId", pirateSquadId);
if(utils.hasLocalVar(commander, "cmd.pirate.initialSize"))
utils.removeLocalVar(commander, "cmd.pirate.initialSize");
utils.setLocalVar(commander, "cmd.pirate.initialSize", pirateForceSize);
if(isIdValid(target))
{
transform targetLoc = getTransform_o2w(target);
//ship_ai.squadLoiter(pirateSquadId, targetLoc, 25.0f, 75.0f); //Set up loiter area - OLD METHOD
transform[]loiterPath = ship_ai.createPatrolPathLoiter(targetLoc, 100.0f, 100.0f); //Set up loiter area
ship_ai.squadPatrol(pirateSquadId, loiterPath); //Set up loiter area
}
else
{
transform targetLoc = getTransform_o2w(ship);
//ship_ai.squadLoiter(pirateSquadId, targetLoc, 25.0f, 75.0f); //Set up loiter area - OLD METHOD
transform[]loiterPath = ship_ai.createPatrolPathLoiter(targetLoc, 100.0f, 100.0f); //Set up loiter area
ship_ai.squadPatrol(pirateSquadId, loiterPath); //Set up loiter area
}
dictionary params = new dictionary();
//make sure they aren't targeting me initially
for(int j = 0; j < squaddyList.length; j++)
{
obj_id thisAttacker = squaddyList[j];
params.put("loopsleft", 2);
params.put("targetship", ship);
messageTo(squaddyList[j], "iAmSpoofed", params, 2.0f, false);
}
//If the player blew their roll, the pirates are after them, otherwise, they're force of nature
if(successLevel == 6)
{
ship_ai.squadAddTarget(pirateSquadId, ship); // if the spawner says attack a single, then attack just the singular target
}
else
{
if(isIdValid(target))
{
if(!space_utils.isPlayerControlledShip(target)) // if the target is not a player, then...
{
int targetSquad = ship_ai.unitGetSquadId(target);
int targetSquadSize = ship_ai.squadGetSize(targetSquad);
if(targetSquadSize > 1) // if the target squad is a group of npc ships, then...
{
obj_id[] targetSquaddyList = null;
if(ship_ai.isSquadIdValid(targetSquad))
targetSquaddyList = ship_ai.squadGetUnitList(targetSquad);
else
return true;
for(int k = 0; k < targetSquaddyList.length; k++)
setObjVar(targetSquaddyList[k], "damageMultiplier", NPC_DAMAGE_MULTIPLIER);
ship_ai.squadSetPrimaryTarget(pirateSquadId, targetSquad); // if the spawner says attack a group, then attack the whole enemy target squad
}
else // if the target isn't a squad of npc ships, just attack the one.
{
if(ship_ai.isSquadIdValid(targetSquad))
{
setObjVar(target, "damageMultiplier", NPC_DAMAGE_MULTIPLIER);
ship_ai.squadSetPrimaryTarget(pirateSquadId, target);
}
else
return true;
}
}
else // if the target is a player, then...
{
//setObjVar(target, "damageMultiplier", NPC_DAMAGE_MULTIPLIER); -- don't do this for player targets
ship_ai.squadSetPrimaryTarget(pirateSquadId, target); // if the spawner says attack a single, then attack just the singular target
//ship_ai.squadAddTarget(pirateSquadId, target); // if the spawner says attack a single, then attack just the singular target
}
}
}
return true;
}
void piratePackageEvac(obj_id commander, int pirateSquadId)
{
debugServerConsoleMsg(null, "PIRATEpACKAGEeVAC");
//clean up the player's localVars
utils.removeLocalVar(commander, "cmd.pirate");
obj_id ship = space_transition.getContainingShip(commander); // THIS LINE MIGHT BE A PROBLEM IF THE REASON WE'RE EVAC'ING THE STRIKE PACKAGE IS BECAUSE THE PLAYER ////LOGGED ON US.
// MIGHT NEED TO GET AN EVAC LOCATION FOR THE BOMBERS TO HEAD TO WITHOUT THE PLAYER.
obj_id[] pirateSquaddyList = null;
if(ship_ai.isSquadIdValid(pirateSquadId))
pirateSquaddyList = ship_ai.squadGetUnitList(pirateSquadId);
else
return;
if(hasObjVar(pirateSquaddyList[0], "evacuate")) //check to see if the bombers are already evacuating. Abort the rest of this function if they are.
return;
//Set an evacuate objvar on all bombers and escort fighters to let them know to ignore the next onDestroy trigger... it's probably them hyperspacing out!
for(int i = 0; i < pirateSquaddyList.length; i++)
{
setObjVar(pirateSquaddyList[i], "evacuate", 1);
}
//issue evacuation-related ai commands to the bombers.
obj_id pirateLeader = pirateSquaddyList[0];
obj_id squadTarget = ship_ai.unitGetPrimaryAttackTarget(pirateLeader);
if(!isIdValid(ship))
ship = pirateLeader; //if the player doesn't exist any more, use the strike leader to determine an evac location
transform loc = playerCommandSpawnerLocGetter(ship, true);
ship_ai.squadSetAttackOrders(pirateSquadId, ship_ai.ATTACK_ORDERS_HOLD_FIRE);
ship_ai.squadMoveTo(pirateSquadId, loc);
if(utils.hasLocalVar(commander, "cmd.pirate.squadId"))
{
int targetSquadId = utils.getIntLocalVar(commander, "cmd.pirate.squadId");
obj_id[] targetSquaddyList = null;
if(ship_ai.isSquadIdValid(targetSquadId))
targetSquaddyList = ship_ai.squadGetUnitList(targetSquadId);
else
return;
for(int i = 0; i < targetSquaddyList.length; i++)
{
if(hasObjVar(targetSquaddyList[i], "damageMultiplier"))
removeObjVar(targetSquaddyList[i], "damageMultiplier");
}
}
return;
}
float getShipWeaponDamage(obj_id objAttacker, obj_id objDefender, int intWeaponSlot)
{
return getShipWeaponDamage(objAttacker, objDefender, intWeaponSlot, false);
}
float getShipWeaponDamage(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, boolean isMissile)
{
const float NPC_NPC_DAMAGE_MULTIPLIER_DEEP_SPACE = 10.0f;
const float NPC_NPC_DAMAGE_MULTIPLIER = 1.0f;
const float PVP_MULTIPLIER = .5f;
const float GUNSHIP_PVP_MULTIPLIER = .25f;
// we dont have firing mode or slot, so they're hardcoded for now./
float fltMinDamage = getShipWeaponDamageMinimum(objAttacker, intWeaponSlot);
float fltMaxDamage = getShipWeaponDamageMaximum(objAttacker, intWeaponSlot);
//////////LOG("space", "min damage is "+fltMinDamage);
//////////LOG("space", "max damage is "+fltMaxDamage);
//////////LOG("space", "weapon slot is "+intWeaponSlot);
float fltGeneralEfficiency = getShipComponentEfficiencyGeneral(objAttacker, intWeaponSlot);
//////////LOG("space", "efficiency is "+fltGeneralEfficiency);
// MODIFY DAMAGE BASED ON EFFEICNECY
fltMinDamage = fltMinDamage * fltGeneralEfficiency;
fltMaxDamage = fltMaxDamage * fltGeneralEfficiency;
float fltDamage = rand(fltMinDamage, fltMaxDamage);
//////////LOG("space", "returning "+fltDamage);
if((!space_utils.isPlayerControlledShip(objAttacker) && (!space_utils.isPlayerControlledShip(objDefender))))
{
location locTest = getLocation(objAttacker);
if(locTest.area.equals("space_heavy"))
{
fltDamage = fltDamage * NPC_NPC_DAMAGE_MULTIPLIER_DEEP_SPACE;
}
else
{
if(hasObjVar(objDefender, "damageMultiplier"))
{
int intTest = getIntObjVar(objDefender, "damageMultiplier");
float fltMultiplier = (float) (intTest);
if(fltMultiplier <= 0)
{
fltMultiplier = 1.0f;
}
fltDamage = fltDamage * fltMultiplier;
}
else
{
fltDamage = fltDamage * NPC_NPC_DAMAGE_MULTIPLIER;
}
}
}
else if(space_utils.isPlayerControlledShip(objAttacker) && (space_utils.isPlayerControlledShip(objDefender)))
{
fltDamage = fltDamage * PVP_MULTIPLIER; // reduction
// PVP damage reduction for gunships attacked with non-missiles
string defenderChassis = getShipChassisType(objDefender);
if(defenderChassis.startsWith("player_gunship") && !isMissile)
{
fltDamage = fltDamage * GUNSHIP_PVP_MULTIPLIER;
}
}
float skillMod = (float)getEnhancedSkillStatisticModifierUncapped(objAttacker, "ship_weapon_damage")/100;
fltDamage = fltDamage * (1.0f + skillMod);
return fltDamage;
}
float doShieldDamage(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, float fltDamage, int intSide)
{
// returns the leftover damage
fltDamage = damageShield(objAttacker, objDefender, intWeaponSlot, fltDamage, intSide);
return fltDamage;
}
float doArmorDamage(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, float fltDamage, int intSide)
{
fltDamage = damageArmor(objAttacker, objDefender, intWeaponSlot, fltDamage, intSide);
return fltDamage;
}
float doChassisDamage(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, float fltDamage)
{
//LOG("space", "Damaging Chassis");
float fltChassisHitPoints = getShipCurrentChassisHitPoints(objDefender);
//LOG("space", "Chassis Hit Points are "+fltChassisHitPoints);
float fltMaximumChassisHitPoints = getShipMaximumChassisHitPoints(objDefender);
if((fltChassisHitPoints - fltDamage) < (fltMaximumChassisHitPoints / 2) && fltChassisHitPoints > (fltMaximumChassisHitPoints / 2))
{
// transition to < 50% hitpoints
dictionary dctParams = new dictionary();
space_utils.notifyObject(objDefender, "OnHullNearlyDestroyed", dctParams);
}
fltChassisHitPoints = fltChassisHitPoints - fltDamage;
doInteriorDamageNotification(objDefender, space_combat.CHASSIS, fltMaximumChassisHitPoints, fltChassisHitPoints);
//LOG("space", "Modiifed Chassis Hit Points are "+fltChassisHitPoints);
//-- play the hit effects on the client(s)
if((fltChassisHitPoints + fltDamage) > 0.0f && fltMaximumChassisHitPoints > 0.0f)
{
location locDefender = getLocation(objDefender);
location locAttacker = isIdValid(objAttacker) ? getLocation(objAttacker) : locDefender;
vector up_w = new vector(locAttacker.x - locDefender.x, locAttacker.y - locDefender.y, locAttacker.z - locDefender.z);
float integrity = fltChassisHitPoints / fltMaximumChassisHitPoints;
float previousIntegrity = (fltChassisHitPoints + fltDamage) / fltMaximumChassisHitPoints;
if(Math.abs(integrity - previousIntegrity) > 0.01f)
notifyShipHit(objDefender, up_w, vector.zero, ship_hit_type.HT_chassis, integrity, previousIntegrity);
}
if(fltChassisHitPoints <= 0)
{
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage + fltChassisHitPoints);
// KABOOM
//LOG("space", "KABOOM ");
location locTest = getLocation(objDefender);
setShipCurrentChassisHitPoints(objDefender, 0);
doChassisDamageSpam(objAttacker, objDefender, fltDamage, fltChassisHitPoints);
return 10;
}
else
{
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage);
if(fltChassisHitPoints > fltMaximumChassisHitPoints)
{
fltChassisHitPoints = fltMaximumChassisHitPoints;
}
doChassisDamageSpam(objAttacker, objDefender, fltDamage, fltChassisHitPoints);
setShipCurrentChassisHitPoints(objDefender, fltChassisHitPoints);
return 0;
}
}
float getShieldHitPoints(obj_id objDefender, int intSide)
{
if(isShipSlotInstalled(objDefender, ship_chassis_slot_type.SCST_shield_0))
{
if(intSide == space_combat.FRONT)
{
return getShipShieldHitpointsFrontCurrent(objDefender);
}
else if(intSide == space_combat.BACK)
{
return getShipShieldHitpointsBackCurrent(objDefender);
}
}
return 0;
}
float getShieldHitPointsMaximum(obj_id objDefender, int intSide)
{
if(isShipSlotInstalled(objDefender, ship_chassis_slot_type.SCST_shield_0))
{
if(intSide == space_combat.FRONT)
{
return getShipShieldHitpointsFrontMaximum(objDefender);
}
else if(intSide == space_combat.BACK)
{
return getShipShieldHitpointsBackMaximum(objDefender);
}
}
return 0;
}
float getArmorHitPoints(obj_id objDefender, int intSide)
{
if(intSide == space_combat.FRONT)
{
// we get the slot, then we get the armor component, then we get the hitpoints on that.
int intSlot = ship_chassis_slot_type.SCST_armor_0;
if(isShipSlotInstalled(objDefender, intSlot))
{
return getShipComponentArmorHitpointsCurrent(objDefender, intSlot);
}
}
else if(intSide == space_combat.BACK)
{
int intSlot = ship_chassis_slot_type.SCST_armor_1;
if(isShipSlotInstalled(objDefender, intSlot))
{
return getShipComponentArmorHitpointsCurrent(objDefender, intSlot);
}
}
return 0;
}
float getArmorHitPointsMaximum(obj_id objDefender, int intSide)
{
if(intSide == space_combat.FRONT)
{
// we get the slot, then we get the armor component, then we get the hitpoints on that.
int intSlot = ship_chassis_slot_type.SCST_armor_0;
if(isShipSlotInstalled(objDefender, intSlot))
{
return getShipComponentArmorHitpointsMaximum(objDefender, intSlot);
}
}
else if(intSide == space_combat.BACK)
{
int intSlot = ship_chassis_slot_type.SCST_armor_1;
if(isShipSlotInstalled(objDefender, intSlot))
{
return getShipComponentArmorHitpointsMaximum(objDefender, intSlot);
}
}
return 0;
}
void setShieldHitPoints(obj_id objDefender, int intSide, float fltHitPoints)
{
if(isShipSlotInstalled(objDefender, ship_chassis_slot_type.SCST_shield_0))
{
if(intSide == space_combat.FRONT)
{
setShipShieldHitpointsFrontCurrent(objDefender, fltHitPoints);
}
else if(intSide == space_combat.BACK)
{
setShipShieldHitpointsBackCurrent(objDefender, fltHitPoints);
}
else
{
//////////LOG("combat", "BAD SIDE");
}
}
}
void setArmorHitPoints(obj_id objDefender, int intSide, float fltHitPoints)
{
if(intSide == space_combat.FRONT)
{
int intSlot = ship_chassis_slot_type.SCST_armor_0;
if(isShipSlotInstalled(objDefender, intSlot))
{
setShipComponentArmorHitpointsCurrent(objDefender, intSlot, fltHitPoints);
}
}
else if(intSide == space_combat.BACK)
{
int intSlot = ship_chassis_slot_type.SCST_armor_1;
if(isShipSlotInstalled(objDefender, intSlot))
{
setShipComponentArmorHitpointsCurrent(objDefender, intSlot, fltHitPoints);
}
}
else
{
//////////LOG("combat", "BAD SIDE");
}
}
//----------------------------------------------------------------------
float damageShield(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, float fltDamage, int intSide)
{
float fltShieldHitPoints = getShieldHitPoints(objDefender, intSide);
//////////LOG("space", "Shield HP: "+fltShieldHitPoints);
if(fltShieldHitPoints > 0)
{
if(isIdValid(objAttacker))
{
if(isShipSlotInstalled(objAttacker, intWeaponSlot))
{
float fltWeaponShieldRating = getShipWeaponEffectivenessShields(objAttacker, intWeaponSlot);
fltDamage = fltDamage * fltWeaponShieldRating;
}
}
int intDamage = (int) fltDamage; // cast to strip decimal points
fltDamage = (float) intDamage;
}
float fltOldShieldHitPoints = fltShieldHitPoints; // store for later.
fltShieldHitPoints = fltShieldHitPoints - fltDamage;
float fltShieldHitPointsMaximum = getShieldHitPointsMaximum(objDefender, intSide);
//-- play the hit effects on the client(s)
if(fltOldShieldHitPoints > 0.0f && fltShieldHitPointsMaximum > 0.0f)
{
location locDefender = getLocation(objDefender);
location locAttacker = isIdValid(objAttacker) ? getLocation(objAttacker) : locDefender;
vector up_w = new vector(locAttacker.x - locDefender.x, locAttacker.y - locDefender.y, locAttacker.z - locDefender.z);
float integrity = fltShieldHitPoints / fltShieldHitPointsMaximum;
float previousIntegrity = (fltShieldHitPoints + fltDamage) / fltShieldHitPointsMaximum;
if(Math.abs(integrity - previousIntegrity) > 0.01f)
notifyShipHit(objDefender, up_w, vector.zero, ship_hit_type.HT_shield, integrity, previousIntegrity);
}
if(fltShieldHitPoints < 0)
{
if(((fltOldShieldHitPoints - fltDamage) < 0) && (fltOldShieldHitPoints > 0))
{
dictionary dctParams = new dictionary();
space_utils.notifyObject(objDefender, "OnShieldsDepleted", dctParams);
}
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage + fltShieldHitPoints);
setShieldHitPoints(objDefender, intSide, 0);
return Math.abs(fltShieldHitPoints); // return the remainder of damage for the given side.
}
else
{
if(intSide == space_combat.FRONT)
{
float fltMaximumShieldHitPoints = getShipShieldHitpointsFrontMaximum(objDefender);
if(((fltOldShieldHitPoints - fltDamage) < fltMaximumShieldHitPoints / 2) && (fltOldShieldHitPoints > (fltMaximumShieldHitPoints / 2)))
{
// transition to < 50% hitpoints
dictionary dctParams = new dictionary();
space_utils.notifyObject(objDefender, "OnShieldsHalf", dctParams);
}
doInteriorDamageNotification(objDefender, space_combat.SHIELD, fltMaximumShieldHitPoints, fltShieldHitPoints);
}
else if(intSide == space_combat.BACK)
{
float fltMaximumShieldHitPoints = getShipShieldHitpointsBackMaximum(objDefender);
if(((fltOldShieldHitPoints - fltDamage) < fltMaximumShieldHitPoints / 2) && (fltOldShieldHitPoints > (fltMaximumShieldHitPoints / 2)))
{
// transition to < 50% hitpoints
dictionary dctParams = new dictionary();
space_utils.notifyObject(objDefender, "OnShieldsHalf", dctParams);
}
doInteriorDamageNotification(objDefender, space_combat.SHIELD, fltMaximumShieldHitPoints, fltShieldHitPoints);
}
setShieldHitPoints(objDefender, intSide, fltShieldHitPoints);
doShieldDamageSpam(objAttacker, objDefender, intSide, fltDamage, fltShieldHitPoints);
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage);
return 0;
}
}
//----------------------------------------------------------------------
float damageArmor(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, float fltDamage, int intSide)
{
float fltArmorHitPoints = getArmorHitPoints(objDefender, intSide);
//////////LOG("space", "ARMOR HITPOINTS ARe "+fltArmorHitPoints);
if(fltArmorHitPoints > 0)
{
if(isIdValid(objAttacker))
{
if(isShipSlotInstalled(objAttacker, intWeaponSlot))
{
float fltWeaponArmorRating = getShipWeaponEffectivenessArmor(objAttacker, intWeaponSlot);
fltDamage = fltDamage * fltWeaponArmorRating;
}
}
// modify the damage based on armor rating for the weapon
int intDamage = (int) fltDamage; // cast to strip decimal points
fltDamage = (float) intDamage;
}
fltArmorHitPoints = fltArmorHitPoints - fltDamage;
float fltMaximumArmorHitPoints = getArmorHitPointsMaximum(objDefender, intSide);
//-- play the hit effects on the client(s)
if((fltArmorHitPoints + fltDamage) > 0.0f && fltMaximumArmorHitPoints > 0.0f)
{
location locDefender = getLocation(objDefender);
location locAttacker = isIdValid(objAttacker) ? getLocation(objAttacker) : locDefender;
vector up_w = new vector(locAttacker.x - locDefender.x, locAttacker.y - locDefender.y, locAttacker.z - locDefender.z);
float integrity = fltArmorHitPoints / fltMaximumArmorHitPoints;
float previousIntegrity = (fltArmorHitPoints + fltDamage) / fltMaximumArmorHitPoints;
if(Math.abs(integrity - previousIntegrity) > 0.01f)
notifyShipHit(objDefender, up_w, vector.zero, ship_hit_type.HT_armor, integrity, previousIntegrity);
}
if(fltArmorHitPoints < 0)
{
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage + fltArmorHitPoints);
setArmorHitPoints(objDefender, intSide, 0);
doArmorDamageSpam(objAttacker, objDefender, intSide, fltDamage + fltArmorHitPoints, 0);
return Math.abs(fltArmorHitPoints); // return the remainder of damage for the given side.
}
else
{
if(intSide == space_combat.FRONT)
{
int intSlot = ship_chassis_slot_type.SCST_armor_0;
doInteriorDamageNotification(objDefender, space_combat.ARMOR, getShipComponentArmorHitpointsMaximum(objDefender, intSlot), fltArmorHitPoints);
}
else if(intSide == space_combat.BACK)
{
int intSlot = ship_chassis_slot_type.SCST_armor_1;
doInteriorDamageNotification(objDefender, space_combat.ARMOR, getShipComponentArmorHitpointsMaximum(objDefender, intSlot), fltArmorHitPoints);
}
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage + fltDamage);
setArmorHitPoints(objDefender, intSide, fltArmorHitPoints);
doArmorDamageSpam(objAttacker, objDefender, intSide, fltDamage, fltArmorHitPoints);
return 0;
}
}
float doComponentDamage(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, int intTargetedComponent, float fltDamage, int intSide)
{
// we figure out if you hit what you aimed at
// then we figure out how the damage is applied and stuff!
//////////LOG("space", "Component 1 is "+intTargetedComponent);
boolean boolNoPassThrough = false; // does damage bleed thoruhg.
if(intTargetedComponent != space_combat.SHIP)
{
if(!isShipSlotInstalled(objDefender, intTargetedComponent))
{
intTargetedComponent = getComponentToDamage(objAttacker, objDefender, intTargetedComponent, intSide);
if(intTargetedComponent == space_combat.SHIP)
{
// no more components.. DIE!
return fltDamage;
}
}
else
{
// we lower our damage to make sure attacking components isn't a shortcut
fltDamage = fltDamage * 1.0f; // SMALL amount of damage
//////////LOG("space", "doign "+fltDamage);
boolNoPassThrough = true;
}
}
else
{
intTargetedComponent = getComponentToDamage(objAttacker, objDefender, intTargetedComponent, intSide);
if(intTargetedComponent == space_combat.SHIP)
{
// no more components.. DIE!
return fltDamage;
}
}
////////LOG("space", "Component 2 is "+intTargetedComponent);
fltDamage = damageComponent(objAttacker, objDefender, intWeaponSlot, intTargetedComponent, fltDamage, intSide, boolNoPassThrough);
////////LOG("space", "Component 3 is "+intTargetedComponent);
if(boolNoPassThrough)
{
return 0; // no0 pass through
}
// we eshould probably do a path check here, and check for disabled ships.....
return fltDamage;
}
dictionary getComponentWeightings(obj_id objDefender, int intTargetedComponent)
{
if(intTargetedComponent != space_combat.SHIP)
{
// we do some checks here
// if they have the correct command, they target the passed in component
// otherwise we kick down to the below loop
// return a length 1 array with the item to target
if(!isShipSlotInstalled(objDefender, intTargetedComponent))
{
intTargetedComponent = space_combat.SHIP;
}
else
{
dictionary dctReturn = new dictionary();
int[] intSlots = new int[1];
int[] intWeightings = new int[1];
intSlots[0] = intTargetedComponent;
intWeightings[0] = 100;
dctReturn.put("intWeightings", intWeightings);
dctReturn.put("intSlots", intSlots);
return dctReturn;
}
}
// returns a dictionary ocntaing our arrays of components.
string strFileName = "datatables/space/ship_chassis.iff";
string strChassisType = getShipChassisType(objDefender);
dictionary dctRow = dataTableGetRow(strFileName, strChassisType);
if(dctRow == null)
{
//////////LOG("space", "NO SHIP CHASSIS DEFINED FOR "+strChassisType);
dctRow = dataTableGetRow(strFileName, "xwing");
}
// we'r egoing to do something wacky
// we get the "component list" for the chassis
// we check if it's installed
// we get the weightings
// we make our calcuated list..
// theoretically we could do this all at runtime, but we might end up optimizing this
// down to doing this on itme change
// im thinking we might want to setup all of this information in the scriptvar
resizeable int[] intWeightings = new int[0];
resizeable int[] intSlots = new int[0];
int[] intRawSlots = getShipChassisSlots(objDefender);
for(int intI = 0; intI < intRawSlots.length; intI++)
{
// returns a list of the slots a ship has
// we gotta get the weighting out of the dictionary
if((isShipSlotInstalled(objDefender, intRawSlots[intI])) && (intRawSlots[intI] != ship_chassis_slot_type.SCST_armor_0) && (intRawSlots[intI] != ship_chassis_slot_type.SCST_armor_1))
{
//////////LOG("space", "Adding "+space_crafting.getComponentSlotNameString(intRawSlots[intI])+" to weightings and slots");
string strSlotName = space_crafting.getComponentSlotNameString(intRawSlots[intI]);
strSlotName = strSlotName + "_hitweight";
intWeightings = utils.addElement(intWeightings, dctRow.getInt(strSlotName));
intSlots = utils.addElement(intSlots, intRawSlots[intI]);
}
else
{
//////////LOG("space", "SPACE BASE for "+objDefender+" has no slot of slot "+space_crafting.getComponentSlotNameString(intRawSlots[intI]));
}
}
if(intWeightings.length == 0)
{
//////////LOG("space", "BAD CHASSIS DEFINED FOR SHIP "+strChassisType);
return null;
}
dictionary dctReturn = new dictionary();
dctReturn.put("intWeightings", intWeightings);
dctReturn.put("intSlots", intSlots);
return dctReturn;
}
int getComponentToDamage(obj_id objAttacker, obj_id objDefender, int intTargetedComponent, int intSide)
{
// we use the above wrapped functions.
// do the weighted thing.
dictionary dctReturn = getComponentWeightings(objDefender, intTargetedComponent);
if(dctReturn == null)
{
// NO COMPONENTS!
return space_combat.SHIP;
}
int[] intSlots = dctReturn.getIntArray("intSlots");
int[] intRawWeightings = dctReturn.getIntArray("intWeightings");
int[] intNewWeightings = new int[intRawWeightings.length * 2];
//////////LOG("combat", "intRawWeighting Length is "+intRawWeightings.length);
//////////LOG("combat", "intNewWeightings Length is "+intNewWeightings.length);
int intCounter = 0;
if(intRawWeightings.length > 1)
{
// no target specified, use 0 weighting and stuff
//////////LOG("combat", "target and defender are same");
int intJ = 0;
for(int intI = 0; intI < intNewWeightings.length; intI = intI + 2)
{
intNewWeightings[intI] = intCounter;
intCounter = intCounter + intRawWeightings[intJ]; //
intJ = intJ + 1;
intNewWeightings[intI + 1] = intCounter;
intCounter = intCounter + 1; //for our next iteration
}
// now we pick our component to whack
int intRoll = rand(0, intNewWeightings[intNewWeightings.length - 1]);
//////////LOG("space", "Roll si "+intRoll);
//////////LOG("space", "intNewWeightings length is "+intNewWeightings.length);
intCounter = 0;
for(int intI = 0; intI < intNewWeightings.length; intI = intI + 2)
{
//////////LOG("space", "intNewWeightnings["+intI+"] is "+intNewWeightings[intI]+" and next one is "+intNewWeightings[intI+1]);
//////////LOG("space", "looking for "+intRoll);
// figure out which one we picked
if((intNewWeightings[intI] <= intRoll) && (intNewWeightings[intI + 1] >= intRoll))
{
// intCounter is our value!
//////////LOG("space", "Found aour value, min is "+intNewWeightings[intI]+" max is "+intNewWeightings[intI+1]);
break;
}
//////////LOG("space", "counter is "+intCounter);
intCounter++;
}
}
else
{
// we pick a single component to damage.
}
int intComponent = intSlots[intCounter];
//////////LOG("combat", "choosing component "+intComponent);
return intComponent;
}
float damageComponent(obj_id objAttacker, obj_id objDefender, int intWeaponSlot, int intComponent, float fltDamage, int intSide, boolean boolTrackDisabled)
{
int intDamage = (int) fltDamage; // cast to strip decimal points
fltDamage = (float) intDamage;
float fltOldComponentArmor = getShipComponentArmorHitpointsCurrent(objDefender, intComponent);
float fltOldComponentHitPoints = getShipComponentHitpointsCurrent(objDefender, intComponent);
float fltComponentArmor = fltOldComponentArmor;
float fltComponentHitPoints = fltOldComponentHitPoints;
////////LOG("space", "fltComponentArmor is "+fltComponentArmor);
////////LOG("space", "fltComponentHitPoints is "+fltComponentHitPoints);
float fltRemainingDamage = 0;
if((fltComponentHitPoints == 0) && (fltComponentArmor == 0))
{
return fltDamage; // Component is NUKED!
}
fltComponentArmor = fltComponentArmor - fltDamage;
////////LOG("space", "Component armor is now "+fltComponentArmor);
if(fltComponentArmor < 0)
{
////////LOG("space", "ARMOR hitpoitns < 0, registering "+fltDamage + fltComponentArmor);
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage + fltComponentArmor);
setShipComponentArmorHitpointsCurrent(objDefender, intComponent, 0);
fltDamage = Math.abs(fltComponentArmor);
fltComponentArmor = 0;
fltComponentHitPoints = fltComponentHitPoints - fltDamage;
if(fltComponentHitPoints < 0)
{
////////LOG("space", "Component hp < 0, registering "+fltDamage + fltComponentHitPoints);
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage + fltComponentHitPoints);
fltRemainingDamage = Math.abs(fltComponentHitPoints);
setShipComponentHitpointsCurrent(objDefender, intComponent, 0);
space_combat.recalculateEfficiency(intComponent, objDefender);
if(boolTrackDisabled)
{
if(space_combat.isShipDisabled(objDefender, intComponent) && !hasObjVar(objDefender, "isDisabled"))
{
dictionary dctParams = new dictionary();
dctParams.put("objAttacker", objAttacker);
dctParams.put("objDefender", objDefender);
if(space_utils.isPlayerControlledShip(objDefender) && (!space_utils.isShipWithInterior(objDefender)))
{
setCondition(objDefender, CONDITION_EJECT);
}
space_utils.notifyObject(objDefender, "OnShipDisabled", dctParams); // self destruct stuff
if(!hasObjVar(objDefender, "noNotifyDisable"))
space_combat.notifyAttackerDisabled(objAttacker, objDefender, dctParams);
setObjVar(objDefender, "isDisabled", getGameTime() + 5);
}
}
else
{
if(space_utils.isPlayerControlledShip(objDefender))
{
if(space_utils.isPlayerControlledShip(objDefender) && (!space_utils.isShipWithInterior(objDefender)))
{
setCondition(objDefender, CONDITION_EJECT);
}
}
}
doComponentDamageSpam(objAttacker, objDefender, intComponent, fltDamage);
fltComponentHitPoints = 0;
}
else
{
////////LOG("space", "Component hp > 0, registering "+fltDamage);
space_combat.recalculateEfficiency(intComponent, objDefender);
doInteriorDamageNotification(objDefender, space_combat.COMPONENT, 90, 100);
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage);
setShipComponentHitpointsCurrent(objDefender, intComponent, fltComponentHitPoints);
space_combat.recalculateEfficiency(intComponent, objDefender);
doComponentDamageSpam(objAttacker, objDefender, intComponent, fltDamage);
fltRemainingDamage = 0;
}
}
else
{
doInteriorDamageNotification(objDefender, space_combat.COMPONENT, 20, 100);
////////LOG("space", "ARMOR HP > 0, registering "+fltDamage);
space_combat.registerDamageDoneToShip(objAttacker, objDefender, fltDamage);
////////LOG("space", "setting "+intComponent +" to "+fltComponentArmor);
setShipComponentArmorHitpointsCurrent(objDefender, intComponent, fltComponentArmor);
doComponentDamageSpam(objAttacker, objDefender, intComponent, fltDamage);
fltRemainingDamage = 0;
}
////////LOG("space", "fltComponentArmor2 is "+fltComponentArmor);
////////LOG("space", "fltComponentHitPoints2 is "+fltComponentHitPoints);
float fltComponentHitpointsArmorMaximum = getShipComponentArmorHitpointsMaximum(objDefender, intComponent) + getShipComponentHitpointsMaximum(objDefender, intComponent);
float fltOldComponentHitpointsArmor = fltOldComponentArmor + fltOldComponentHitPoints;
//-- play the hit effects on the client(s)
if(fltOldComponentHitpointsArmor > 0.0f && fltComponentHitpointsArmorMaximum > 0.0f)
{
float fltComponentHitpointsArmor = fltComponentArmor + fltComponentHitPoints;
location locDefender = getLocation(objDefender);
location locAttacker = isIdValid(objAttacker) ? getLocation(objAttacker) : locDefender;
vector up_w = new vector(locAttacker.x - locDefender.x, locAttacker.y - locDefender.y, locAttacker.z - locDefender.z);
float integrity = fltComponentHitpointsArmor / fltComponentHitpointsArmorMaximum;
float previousIntegrity = (fltOldComponentHitpointsArmor) / fltComponentHitpointsArmorMaximum;
if(Math.abs(integrity - previousIntegrity) > 0.01f)
notifyShipHit(objDefender, up_w, vector.zero, ship_hit_type.HT_component, integrity, previousIntegrity);
}
// Do our setting if the component still exists
return fltRemainingDamage;
}
string getSideName(int intSide)
{
if(intSide == space_combat.FRONT)
{
return "Front";
}
if(intSide == space_combat.BACK)
{
return "Back";
}
return "";
}
void doShieldDamageSpam(obj_id objAttacker, obj_id objDefender, int intSide, float fltDamage, float fltRemainingHitPoints)
{
if(!space_utils.isShip(objAttacker) || (!space_utils.isShip(objDefender)))
{
return;
}
obj_id objAttackerPilot = getPilotId(objAttacker);
obj_id objDefenderPilot = getPilotId(objDefender);
if(isIdValid(objAttackerPilot) && hasObjVar(objAttackerPilot, "intCombatDebug"))
{
if(fltDamage > 0)
{
string strSide = getSideName(intSide);
sendSystemMessageTestingOnly(objAttackerPilot, "Succesful Shield Hit! Side: " + strSide + " Damage:" + fltDamage + " Remaining Shield Points:" + fltRemainingHitPoints);
}
}
if(isIdValid(objDefenderPilot))
{
//sendSystemMessageTestingOnly(objDefenderPilot, "Your Shield was Hit! Side:"+strSide+" Damage:"+fltDamage+" Remaining Shield Points:"+fltRemainingHitPoints);
}
return;
}
void doArmorDamageSpam(obj_id objAttacker, obj_id objDefender, int intSide, float fltDamage, float fltRemainingHitPoints)
{
if(!space_utils.isShip(objAttacker) || (!space_utils.isShip(objDefender)))
{
return;
}
obj_id objAttackerPilot = getPilotId(objAttacker);
obj_id objDefenderPilot = getPilotId(objDefender);
if(!isIdValid(objAttackerPilot))
{
return;
}
if(hasObjVar(objAttackerPilot, "intCombatDebug"))
{
if(fltDamage > 0)
{
string strSide = getSideName(intSide);
if(isIdValid(objAttackerPilot))
{
//sendSystemMessageTestingOnly(objAttackerPilot, "Succesful Armor Hit! Side:"+strSide+" Damage:"+fltDamage+" Remaining Armor Points:"+fltRemainingHitPoints);
}
}
}
if(isIdValid(objDefenderPilot))
{
//sendSystemMessageTestingOnly(objDefenderPilot, "Your Armor was Hit! Side:"+strSide+" Damage:"+fltDamage+" Remaining Armor Points:"+fltRemainingHitPoints);
}
return;
}
void doComponentDamageSpam(obj_id objAttacker, obj_id objDefender, int intComponent, float fltDamage)
{
if(!space_utils.isShip(objAttacker) || (!space_utils.isShip(objDefender)))
{
return;
}
obj_id objAttackerPilot = getPilotId(objAttacker);
obj_id objDefenderPilot = getPilotId(objDefender);
if(!isIdValid(objAttackerPilot))
{
return;
}
if(hasObjVar(objAttackerPilot, "intCombatDebug"))
{
if(fltDamage > 0)
{
float fltHp = getShipComponentHitpointsCurrent(objDefender, intComponent);
float fltGeneralEfficiency = getShipComponentEfficiencyGeneral(objDefender, intComponent);
float fltEnergyEfficiency = getShipComponentEfficiencyEnergy(objDefender, intComponent);
float fltArmor = getShipComponentArmorHitpointsCurrent(objDefender, intComponent);
if(isIdValid(objAttackerPilot))
{
sendSystemMessageTestingOnly(objAttackerPilot, "Succesful Component Hit! Component Name:" + space_crafting.getComponentSlotNameString(intComponent) + " Damage:" + fltDamage);
}
if(fltHp <= 0)
{
if(isIdValid(objAttackerPilot))
{
sendSystemMessageTestingOnly(objAttackerPilot, "Component Destroyed!");
}
}
else
{
if(isIdValid(objAttackerPilot))
{
sendSystemMessageTestingOnly(objAttackerPilot, "Component Armor Integrity:" + fltArmor + " Component Energy Efficacy:" + fltEnergyEfficiency + "%" + " General Efficiency: " + fltGeneralEfficiency);
}
}
}
}
if(isIdValid(objDefenderPilot))
{
//sendSystemMessageTestingOnly(objDefenderPilot, "A Component Was Hit! Component Name:"+space_crafting.getComponentSlotNameString(intComponent)+" Damage:"+fltDamage);
}
/* if(fltHp<=0)
{
if(isIdValid(objDefenderPilot))
{
//sendSystemMessageTestingOnly(objDefenderPilot, "Component Destroyed!");
}
}
else
{
if(isIdValid(objDefenderPilot))
{
//sendSystemMessageTestingOnly(objDefenderPilot, "Component Armor Integrity:"+fltArmor+" Component Energy Efficacy:"+fltEnergyEfficiency+"%"+" General Efficiency: "+fltGeneralEfficiency);
}
}
*/
return;
}
void doChassisDamageSpam(obj_id objAttacker, obj_id objDefender, float fltDamage, float fltRemainingHitPoints)
{
if(!space_utils.isShip(objAttacker) || !space_utils.isShip(objDefender))
{
return;
}
obj_id objAttackerPilot = getPilotId(objAttacker);
if(!isIdValid(objAttackerPilot))
{
return;
}
obj_id objDefenderPilot = getPilotId(objDefender);
if(hasObjVar(objAttackerPilot, "intCombatDebug"))
{
if(fltDamage > 0)
{
if(isIdValid(objAttackerPilot))
{
sendSystemMessageTestingOnly(objAttackerPilot, "Succesful Chasis Hit! Damage:" + fltDamage + " Reamining Chassis Integrity:" + fltRemainingHitPoints);
}
}
}
if(isIdValid(objDefenderPilot))
{
//sendSystemMessageTestingOnly(objDefenderPilot, "Your Chasis was hit! Damage:"+fltDamage+" Reamining Chassis Integrity:"+fltRemainingHitPoints);
}
return;
}
void doInteriorDamageNotification(obj_id objShip, int intDamageType, float fltCurrentHitpoints, float fltMaximumHitpoints)
{
//////////LOG("space", "checking");
if(hasScript(objShip, "space.ship.ship_interior"))
{
dictionary dctParams = new dictionary();
dctParams.put("intDamageType", intDamageType);
int intDamageIntensity = space_combat.LIGHT;
if((fltCurrentHitpoints > (fltMaximumHitpoints / 2)))
{
intDamageIntensity = space_combat.HEAVY;
}
dctParams.put("intDamageIntensity", intDamageIntensity);
space_utils.notifyObject(objShip, "interiorDamageNotification", dctParams);
//////////LOG("space", "notifying "+objShip);
}
}
void checkAndPerformCombatTaunts(obj_id objTaunter, obj_id objTauntee, string strLocalVar, string strType, float fltRange)
{
const int TAUNT_DELAY = 3;
const int TAUNT_QUANTITY = 5;
const int TAUNT_LISTEN_DELAY = 2;
// get diction
// figure ou tevent
// if we're dying, get everyone in an area
////LOG("space", "Checking "+strLocalVar+" and "+strType);
if((isIdValid(objTauntee) && (!space_utils.isPlayerControlledShip(objTauntee))))
{
////LOG("space", "Non Player tauntee");
return;
}
if((isIdValid(objTaunter) && (space_utils.isPlayerControlledShip(objTaunter))))
{
////LOG("space", "PLayer TAaunter");
return;
}
obj_id objOwner = getOwner(objTauntee);
if(hasObjVar(objOwner, "jtl.combatTauntsDisabled"))
{
return; // no taunts
}
int intGameTime = getGameTime();
int intLastTime = 0;
if(isIdValid(objTaunter))
{
intLastTime = utils.getIntLocalVar(objTaunter, "intTauntTime");
if(((intGameTime - intLastTime) < TAUNT_DELAY))
{
////LOG("space", "No taunt, intGameTime is "+intGameTime+" last time was "+intLastTime);
return;
}
}
if(isIdValid(objTauntee))
{
intLastTime = utils.getIntLocalVar(objTauntee, "intTauntTime");
if(((intGameTime - intLastTime) < TAUNT_DELAY))
{
////LOG("space", "No taunt for tuantee");
return;
}
}
float fltChance = utils.getFloatLocalVar(objTaunter, strLocalVar);
float fltRoll = rand();
fltRoll = fltRoll * 100;
fltChance = fltChance * 100;
//float fltRoll = 0;
////LOG("space", "fltChance is "+fltChance +"roll is "+fltRoll);
if(fltRoll < fltChance)
{
// DO A TAUNT
string strDiction = utils.getStringLocalVar(objTaunter, "strTauntDiction");
if((strDiction != null) && (strDiction != ""))
{
string strFileName = "space/taunts/" + strDiction;
strType = strType + rand(1, TAUNT_QUANTITY);
string_id strSpam = new string_id(strFileName, strType);
if(fltRange > 0)
{
obj_id[] objPlayerShips = getObservedPlayerShips(objTaunter, true);
if(objPlayerShips != null)
{
for(int intI = 0; intI < objPlayerShips.length; intI++)
{
intLastTime = utils.getIntLocalVar(objPlayerShips[intI], "intTauntTime");
if(((intGameTime - intLastTime) > TAUNT_LISTEN_DELAY))
{
if((getDistance(objPlayerShips[intI], objTaunter) < fltRange))
{
prose_package pp = new prose_package();
pp.stringId = strSpam;
pp.actor.set(objOwner);
pp.target.set(objOwner);
space_utils.tauntShip(objPlayerShips[intI], objTaunter, pp, true, false, true, true);
utils.setLocalVar(objTaunter, "intTauntTime", intGameTime);
utils.setLocalVar(objTauntee, "intTauntTime", intGameTime);
}
}
}
}
}
else
{
prose_package pp = new prose_package();
pp.stringId = strSpam;
pp.actor.set(objOwner);
pp.target.set(objOwner);
space_utils.tauntShip(objTauntee, objTaunter, pp, true, false, true, true);
utils.setLocalVar(objTaunter, "intTauntTime", intGameTime);
utils.setLocalVar(objTauntee, "intTauntTime", intGameTime);
}
}
}
}
void setupCapitalShipFromTurretDefinition(obj_id objShip, string strDefinition)
{
string strFileName = "datatables/space_combat/turret_definitions/" + strDefinition + ".iff";
//LOG("space", "fileName is "+strFileName);
string[] strSlots = dataTableGetStringColumn(strFileName, "strSlot");
int[] intComponents = dataTableGetIntColumn(strFileName, "intComponent"); // crc
float[] fltComponentHitpoints = dataTableGetFloatColumn(strFileName, "fltComponentHitpoints");
float[] fltArmorHitpoints = dataTableGetFloatColumn(strFileName, "fltArmorHitpoints");
float[] fltMinDamage = dataTableGetFloatColumn(strFileName, "fltMinDamage");
float[] fltMaxDamage = dataTableGetFloatColumn(strFileName, "fltMaxDamage");
float[] fltRefire = dataTableGetFloatColumn(strFileName, "fltRefire");
float[] fltDrain = dataTableGetFloatColumn(strFileName, "fltDrain");
float[] fltShieldEfficiency = dataTableGetFloatColumn(strFileName, "fltShieldEfficiency");
float[] fltArmorEfficiency = dataTableGetFloatColumn(strFileName, "fltArmorEfficiency");
//LOG("space", "fileName is "+strFileName);
for(int intI = 0; intI < strSlots.length; intI++)
{
if(intComponents[intI] != 0)
{
int intSlot = space_crafting.getComponentSlotInt(strSlots[intI]);
//LOG("space", "equipping to "+strSlots[intI]+" intSlot is "+intSlot);
// use pseudoinstallcomponent
if(!shipPseudoInstallComponent(objShip, intSlot, intComponents[intI]))
{
//LOG("space", "COULDNT MAKE "+strSlots[intI]+" ITEM "+intComponents[intI]);
}
else
{
setShipSlotTargetable(objShip, intSlot, true);
setShipComponentArmorHitpointsMaximum(objShip, intSlot, fltArmorHitpoints[intI]);
setShipComponentArmorHitpointsCurrent(objShip, intSlot, fltArmorHitpoints[intI]);
setShipComponentHitpointsMaximum(objShip, intSlot, fltComponentHitpoints[intI]);
setShipComponentHitpointsCurrent(objShip, intSlot, fltComponentHitpoints[intI]);
setShipWeaponDamageMaximum(objShip, intSlot, fltMinDamage[intI]);
setShipWeaponDamageMinimum(objShip, intSlot, fltMaxDamage[intI]);
setShipWeaponEffectivenessShields(objShip, intSlot, fltShieldEfficiency[intI]);
setShipWeaponEffectivenessArmor(objShip, intSlot, fltShieldEfficiency[intI]);
setShipWeaponEnergyPerShot(objShip, intSlot, fltDrain[intI]);
setShipWeaponRefireRate(objShip, intSlot, fltRefire[intI]);
setShipWeaponEfficiencyRefireRate(objShip, intSlot, 1.0f);
setShipComponentEfficiencyGeneral(objShip, intSlot, 1.0f);
setShipComponentEfficiencyEnergy(objShip, intSlot, 1.0f);
}
}
}
// reset pilot type
string strPilotType = getStringObjVar(objShip, "ship.pilotType");
ship_ai.unitSetPilotType(objShip, strPilotType);
return;
}
void playCombatTauntSound(obj_id objPlayer)
{
string[] strSounds =
{
"sound/sys_comm_generic.snd",
"sound/sys_comm_imperial.snd",
"sound/sys_comm_rebel.snd"
};
if(!isIdValid(objPlayer))
{
return;
}
playMusic(objPlayer, strSounds[rand(0, strSounds.length - 1)]);
}
transform getClosestStationRespawnLocation(obj_id objShip)
{
obj_id objClosestStation = getClosestSpaceStation(objShip);
if(!isIdValid(objClosestStation) || !exists(objClosestStation))
{
return null;
}
transform trTest = space_utils.getRandomPositionInSphere(getTransform_o2p(objClosestStation), 425f, 450f, false);
vector vctTest = space_utils.getVector(objClosestStation);
transform trFinalTransform = space_utils.faceTransformToVector(trTest, vctTest);
return trFinalTransform;
}
location getClosestStationLocation(obj_id objShip)
{
obj_id objClosestStation = getClosestSpaceStation(objShip);
if(!isIdValid(objClosestStation) || !exists(objClosestStation))
{
return null;
}
return getLocation(objClosestStation);
}
void sendDestructionNotification(obj_id objShip, obj_id objAttacker)
{
if(space_utils.isPlayerControlledShip(objShip))
{
resizeable obj_id[] objOfficers = space_utils.getShipOfficers(objShip);
dictionary dctParams = new dictionary();
dctParams.put("objAttacker", objAttacker);
dctParams.put("objShip", objShip);
for(int intI = 0; intI < objOfficers.length; intI++)
{
space_utils.notifyObject(objOfficers[intI], "playerShipDestroyed", dctParams);
}
}
return;
}
void clearHyperspace(obj_id objShip)
{
if(utils.hasScriptVar(objShip, "intHyperspacing"))
{
utils.removeScriptVar(objShip, "intHyperspacing");
}
if(utils.hasScriptVar(objShip, "intHyperspaceDelayStamp"))
{
utils.removeScriptVar(objShip, "intHyperspaceDelayStamp");
}
obj_id objPilot = getPilotId(objShip);
if(isIdValid(objPilot))
{
hyperspaceRestoreShipOnClientFromAbortedHyperspace(objPilot);
}
}
void doDeathCleanup(obj_id self)
{
if(hasObjVar(self, "intAlarmsOn"))
{
space_crafting.turnOffInteriorAlarms(self);
setObjVar(self, "intAlarmsOn", 1);
}
utils.removeScriptVar(self, "intHyperspacing");
}
void setDeathFlags(obj_id objShip)
{
//LOG("space", "setting death flags on "+objShip);
utils.setScriptVar(objShip, "intDestroyed", getGameTime());
return;
}
void clearDeathFlags(obj_id objShip)
{
//LOG("space", "clearingdeath flags on "+objShip);
utils.removeScriptVar(objShip, "intDestroyed");
utils.removeScriptVar(objShip, "intPVPKill");
return;
}
boolean hasDeathFlags(obj_id objShip)
{
//LOG("space", "checking death flags on "+objShip);
if(utils.hasScriptVar(objShip, "intDestroyed"))
{
int intTime = getGameTime();
int intFlagTime = utils.getIntScriptVar(objShip, "intDestroyed");
int intDifference = intTime - intFlagTime;
if(intDifference > 20)
{
utils.removeScriptVar(objShip, "intDestroyed");
//LOG("space", "clearing 20 second "+objShip);
return false;
}
//LOG("space", "hAs deaht flags"+objShip);
return true;
}
//LOG("space", "No death flags"+objShip);
return false;
}
void addModuleToDatapad(obj_id objModule, obj_id objDatapad)
{
string strDroidCommand = getStringObjVar(objModule, "strDroidCommand");
int programSize = 1;
if(hasObjVar(objModule, "programSize"))
{
programSize = getIntObjVar(objModule, "programSize");
addModuleToDatapad(strDroidCommand, objDatapad, programSize);
destroyObject(objModule);
}
else
{
addModuleToDatapad(strDroidCommand, objDatapad);
}
return;
}
void addModuleToDatapad(string strDroidCommand, obj_id objDatapad)
{
int programSize = space_pilot_command.getDroidProgramSize(strDroidCommand, null);
addModuleToDatapad(strDroidCommand, objDatapad, programSize);
return;
}
void addModuleToDatapad(string strDroidCommand, obj_id objDatapad, int intProgramSize)
{
string programDataTemplate = "object/intangible/data_item/droid_command.iff"; //This is a volume one object template
switch (intProgramSize)
{
case 35:
programDataTemplate = "object/intangible/data_item/droid_command_5.iff";
break;
case 25:
programDataTemplate = "object/intangible/data_item/droid_command_4.iff";
break;
case 24:
programDataTemplate = "object/intangible/data_item/droid_command_4_2.iff";
break;
case 20:
programDataTemplate = "object/intangible/data_item/droid_command_3.iff";
break;
case 19:
programDataTemplate = "object/intangible/data_item/droid_command_3_2.iff";
break;
case 10:
programDataTemplate = "object/intangible/data_item/droid_command_2.iff";
break;
case 5:
programDataTemplate = "object/intangible/data_item/droid_command_1.iff";
break;
}
obj_id objNewCommand = createObject(programDataTemplate, objDatapad, "");
setObjVar(objNewCommand, "strDroidCommand", strDroidCommand);
setName(objNewCommand, new string_id("space/droid_commands", strDroidCommand + "_chipname"));
setObjVar(objNewCommand, "programSize", intProgramSize);
return;
}
void doBattlefieldRepairCheck(obj_id objShip)
{
location locTest = getLocation(objShip);
if(locTest.area.equals("space_heavy1"))
{
// repair
obj_id objPlayer = getOwner(objShip);
space_crafting.repairDamage(objPlayer, objShip, 1.0f, 0); // now we fix the ship
}
return;
}
void simpleShieldRatioRebalance(obj_id ship)
{
float fltShieldFrontMaximum = getShipShieldHitpointsFrontMaximum(ship);
float fltShieldBackMaximum = getShipShieldHitpointsBackMaximum(ship);
if(fltShieldFrontMaximum != fltShieldBackMaximum)
{
float fltShieldTotal = fltShieldFrontMaximum + fltShieldBackMaximum;
float fltFrontMax = (fltShieldTotal / 2);
float fltBackMax = fltShieldTotal - fltFrontMax;
setShipShieldHitpointsFrontMaximum(ship, fltFrontMax);
setShipShieldHitpointsBackMaximum(ship, fltBackMax);
}
return;
}
boolean isCapShip(obj_id ship)
{
return (dataTableGetInt("datatables/space_mobile/space_mobile.iff", getStringObjVar(ship, "ship.shipName"), "shipClass") == 2); //2 is capital ship.
}
boolean getCollectionLoot(obj_id objAttacker, obj_id objPilot, obj_id objContainer, string collectionLoot)
{
if(!isIdValid(objAttacker))
return false;
if(!isIdValid(objPilot))
return false;
if(!isIdValid(objContainer))
return false;
if(collectionLoot.equals(""))
return false;
//test here for multiple collections in "collectionLoot" and choose 1
string[] collectionsInColumn = split(collectionLoot, ',');
int collectionIndex = rand(0, (collectionsInColumn.length - 1));
collectionLoot = collectionsInColumn[collectionIndex];
//get list of collection loot items and select one
string[] lootArray = dataTableGetStringColumnNoDefaults(SPACE_COLLECTIONS_LOOT_TABLE, collectionLoot);
int max = lootArray.length -1;
int idx = rand(0, max);
string lootToGrant = lootArray[idx]; // specific collectible selected
attemptToGrantLootItem(lootToGrant, objAttacker, objContainer);
return true;
}
boolean attemptToGrantLootItem(string lootItem, obj_id objAttacker, obj_id objContainer)
{
//This is the ship
if(!isIdValid(objAttacker))
return false;
if(!isIdValid(objContainer))
return false;
if(lootItem.equals(""))
return false;
//With this fantastic system we can receive a NULL and we assume it was
//because the inventory was full. Beautiful legacy engineering.
obj_id objItem = space_utils.createObjectTrackItemCount(lootItem, objContainer);
if(isIdValid(objItem))
{
sendItemNotification(objAttacker, objItem);
return true;
}
// Either the item is bad or the container is full
string_id strSpam = new string_id("space/space_loot", "no_more_loot");
if(space_utils.isShipWithInterior(objAttacker))
{
strSpam = new string_id("space/space_loot", "loot_box_full");
}
space_utils.sendSystemMessageShip(objAttacker, strSpam, true, true, true, true);
CustomerServiceLog("space_loot", "Failed to create " + lootItem + " in " + objContainer + " contained by " + objAttacker + ". The Ship or Player Inventory container was full.", getOwner(objAttacker));
return false;
}