// 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 has looted a credit chip worth " 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 has looted a credit chip worth " 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 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; }