mirror of
https://github.com/SWG-Source/dsrc.git
synced 2026-07-29 23:15:55 -04:00
6318 lines
204 KiB
Plaintext
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;
|
|
}
|