FORM U%PAC1HEAD # øåÔÜ&*7@QWUZT
WW
àDATA S6
MORE SECTOR RESOURCES
This Mod alters the terrain so that you have a considerable number of resources available to you for mining and atmospheric processing needs. Also as you mine the resources and process the atmosphere, the map will reflect that fact, not only for Mars Rock and Mars Soil, but also for Argon, Carbon Dioxide and Nitrogen.
IMPORTANT!
Important things to consider when using this Mod:
You must start a new game when using this mod in order for the changes in terrain resources to be reflected.
Other Mods by me:
Digitized Resource Transport
Epic Resource Barrels
Mobile Lab Construction
Enjoy!//=================================================================
// all classes inherited from this will be serialized!
//=================================================================
class Body;
class Location;
class ScienceTarget;
class VehicleObject;
class CharacterObject;
class VehicleDef;
class InstrumentDef;
class Vehicle_Handler;
class Ragdoll_Handler;
class Inventory;
class InventoryItemObject;
InventoryItemObject Global_InvItems_List[MAX_TKOMENTITY_LIST];
int Global_InvItems_EntityNum;
void Global_AddInvItem(InventoryItemObject itm)
{
if (Global_InvItems_EntityNum < MAX_TKOMENTITY_LIST) {
Global_InvItems_List[Global_InvItems_EntityNum] = itm;
Global_InvItems_EntityNum++;
}
}
void Global_RemoveInvItem(InventoryItemObject itm)
{
int itmID = -1;
for (int i = 0; i < Global_InvItems_EntityNum; i++) {
if (itm == Global_InvItems_List[i]) {
Global_InvItems_List[i] = NULL;
itmID = i;
break;
}
}
if (itmID != -1) {
for (i = itmID; i < Global_InvItems_EntityNum; i++) {
Global_InvItems_List[i] = NULL;
if (Global_InvItems_EntityNum > i + 1)
Global_InvItems_List[i] = Global_InvItems_List[i + 1];
}
Global_InvItems_EntityNum--;
}
}
int Global_HighestInvItemID;
int Global_GetHighestInvItemID();
InventoryItemObject Global_GetInventoryItemByID(int id);
void Global_ClearInvItemList()
{
Global_HighestInvItemID = 0;
for (int i = 0; i < MAX_TKOMENTITY_LIST; i++)
{
Global_InvItems_List[i] = NULL;
}
Global_InvItems_EntityNum = 0;
}
class Vehicle_Part extends TKOM_Entity;
class Vehicle_Handler extends Vehicle_Part;
class Controller;
void DeleteStorageObject(VehicleObject vehicle);
//class types
const int GameObjectType = 1;
const int VehicleObjectType = 2;
const int ScienceTargetType = 3;
const int STargetZoneType = 4;
const int LocationObjectType = 5;
const int TRIGGER_MAXLINKS = 16;
const int BUILDBLOCK_MAXCHARACTERSEATS = 4;
const int BUILDBLOCK_RESCOSTMAX = 11;
const int BUILDBLOCK_RESSTOREMAX = 16;
const int BUILDBLOCK_SLOTSMAX = 32;
const int BUILDBLOCK_ATMONORMALSMAX = 16;
const int BUILDBLOCK_ATMOZONESMAX = 8;
const int GROUP_BUILDBLOCK_MAXGROUPS = 4096;
const int GROUP_BUILDBLOCK_MAXBLOCKS = 4096;
const int INVENTORY_SLOTS_MAX = 64;
const int INVENTORY_VALIDSLOTS_MAX = 8;
const int INVENTORY_PEROBJECT_MAX = 48;
const int INVENTORY_OPTIONS_MAX = 6;
const int SATELLITE_CAM = 29;
const float SATELLITE_CAM_FOVMIN = 180;
const float SATELLITE_CAM_FOVMAX = 90000;
const int CAMS_MAX = 6;
const int CAMS_FOCALPOINTS = 5;
const int CAMS_CMD_TAKEPHOTOCAM = 28;
const int MAX_SCANS_CMDS = 64;
const int MAX_DOCKPORTS = 8;
const int MAX_LADDERS = 16;
const int MAX_PASSENGERS_PER_VEHICLE = 16;
const int MAX_SCANS_PER_VEHICLE = 50;
const int MAX_PHOTOS_PER_VEHICLE = 50;
const int MAX_SCIENCE_TARGETS_PER_LOCATION = 512;
const int MAX_SCIENCE_TARGET_ONCOMP = 64;
const int MAX_SCIENCE_TARGET_CHILDS = 64;
const int MAX_SCIENCE_TARGET_ZONES = 64;
const int MAX_SCIENCE_TARGET_NESTING = 128;
const int MAX_SCIENCE_TARGET_ANZ_SPECINST = 64;
const int MAX_VEHICLES_PER_LOCATION = 256;
const int MAX_VEHICLES_LOG_ENTRIES = 1024;
const int MAX_VEHICLES_COMMANDS_PACKET = 20;
const int MAX_VEHICLES_COMMANDS = 1024;
const int MAX_VEHICLES_COMMANDS_TYPES = 1024;
const int MAX_VEHICLES_COMMANDS_TYPESMAX = 6;
const int MAX_VEHICLES_COMMAND_PARTS = 10;
const int MAX_VEHICLES_COMMAND_PARSEPARTS = 40;
const int MAX_VEHICLES_GENSTRINGNUM = 16;
const float MAX_VEHICLES_COMMAND_WAITTIME = 1;
const int MAX_LOCATIONS = 256;
const int MAX_WEATHERFORECAST_HOURS = 168; // 1 week
const float MAX_WEATHERFORECAST_MAXHOURLYCHANGE = 0.3;
const int MAX_RAGDOLLS_PER_LOCATION = 256;
const int PHOTO_IMAGE_WIDTH = 1920;
const int PHOTO_IMAGE_HEIGHT = 1080;
const int PHOTO_LOGOUTIMAGE_WIDTH = 640;
const int PHOTO_LOGOUTIMAGE_HEIGHT = 360;
const int TEAM_MAXNUM = 64;
const int TEAM_DEFAULT = 0;
const float GRAVITY_LOW = 6;
const float GRAVITY_ULTRALOW = 1;
const float GRAVITY_ZERO = 0.1;
int gDuplicateSearch; // Used to search for duplicates in science targets
//=================================================================
// photo object
//=================================================================
class Photo extends CampaignObject
{
string filePath;
ScienceTarget mission;
Location location;
int year;
int month;
int day;
int hour;
int minute;
int second;
string msg;
bool IsGreatherThan(Photo other)
{
if(year != other.year)
{
if(year > other.year)
return true;
else
return false;
}
if(month != other.month)
{
if(month > other.month)
return true;
else
return false;
}
if(day != other.day)
{
if(day > other.day)
return true;
else
return false;
}
if(hour != other.hour)
{
if(hour > other.hour)
return true;
else
return false;
}
if(minute != other.minute)
{
if(minute > other.minute)
return true;
else
return false;
}
if(second != other.second)
{
if(second > other.second)
return true;
else
return false;
}
return false;
}
string GetDateString()
{
string date = itoal(day, 2) + "." + itoal(month, 2) + "." + itoal(year, 4);
string time = itoal(hour, 2) + ":" + itoal(minute, 2) + ":" + itoal(second, 2);
return date + " " + time;
}
string GetPreviewFilePath()
{
int len = strlen(filePath);
if(len <= 4)
return "";
return substr(filePath, 0, len - 4) + "_prev.jpg";
}
string GetTitle();
string GetDescription();
void Photo()
{
}
}
const int GUI3DEVENT_CLICK = 0;
const int GUI3DEVENT_MOUSEENTER = 1;
const int GUI3DEVENT_MOUSELEAVE = 2;
const int GUI3DEVENT_MOUSEDOWN = 3;
const int GUI3DEVENT_MOUSEUP = 4;
//=================================================================
// 3D GUI widget handler class (supports sending GUI events over net)
//=================================================================
class GUI3DWidgetHandler extends ScriptedWidgetEventHandler
{
GUI3DHandler gui3dHandler;
widget rootWidget;
TKOM_Entity owner;
int id;
ButtonWidget cursor2DBtnPressed;
void GUI3DWidgetHandler()
{
gui3dHandler = NULL;
owner = NULL;
id = -1;
}
void ~GUI3DWidgetHandler()
{
if (gui3dHandler)
delete gui3dHandler;
gui3dHandler = NULL;
}
bool IsLocalUsing3DGUI()
{
if (!gui3dHandler)
return false;
if (CurrentGUI3DHandler == gui3dHandler)
return true;
return false;
}
bool IsServer();
bool IsClient();
bool IsMultiplayer();
string GetWidgetPath(widget w)
{
if (!w)
return "";
widget wParent = w;
string result = "";
while (wParent && wParent != rootWidget)
{
if (result != "")
result = wParent.GetName() + "." + result;
else
result = wParent.GetName();
wParent = wParent.GetParent();
}
return result;
}
string GetFullWidgetPath(widget w)
{
if (!w)
return "";
widget wParent = w;
string result = "";
while (wParent)
{
if (result != "")
result = wParent.GetName() + "." + result;
else
result = wParent.GetName();
wParent = wParent.GetParent();
}
return result;
}
void HandleWidgetClick(widget w)
{
if (!w)
return;
string type = w.GetTypeName();
switch(type)
{
case "ButtonWidget":
{
ButtonWidget wButton = (ButtonWidget)w;
if (wButton.GetState())
wButton.SetState(false);
else
wButton.SetState(true);
}
}
}
void MPSafe_OnClick(widget w, int x, int y, int button)
{
return;
}
void MPSafe_OnMouseEnter(widget w, int x, int y)
{
return;
}
void MPSafe_OnMouseLeave(widget w, int x, int y)
{
return;
}
void MPSafe_OnMouseButtonDown(widget w, int x, int y, int button)
{
return;
}
void MPSafe_OnMouseButtonUp(widget w, int x, int y, int button)
{
return;
}
int NeedNetUpdate()
{
return 0;
}
void OnNetInitSend( PacketOutputAdapter output )
{
}
void OnNetInitReceived( PacketInputAdapter input )
{
}
void OnNetUpdate( PacketOutputAdapter output )
{
}
bool OnNetMessage( PacketInputAdapter input )
{
return true;
}
void RP_OnClick(widget w, int x, int y, int button, bool pressedState, bool isRemoteCall);
void RP_OnMouseEnter(widget w, int x, int y, bool isRemoteCall);
void RP_OnMouseLeave(widget w, int x, int y, bool isRemoteCall);
void RP_OnMouseButtonDown(widget w, int x, int y, int button, bool isRemoteCall);
void RP_OnMouseButtonUp(widget w, int x, int y, int button, bool isRemoteCall);
bool OnRPC(int proc, PacketInputAdapter input);
bool OnClick(widget w, int x, int y, int button)
{
if (!IsLocalUsing3DGUI())
return false;
if(w.GetFlags() & WF_DISABLED)
return false;
ButtonWidget btn = NULL;
if (IsInherited(w, Type("ButtonWidget")))
btn = (ButtonWidget)w;
if (IsMultiplayer())
{
//HandleWidgetClick(w);
if (btn)
RP_OnClick(w, x, y, button, btn.GetState(), false);
else
RP_OnClick(w, x, y, button, false, false);
}
else
{
UniversalClassWithWidgetEvent("OnClick", this, w, x, y, button);
MPSafe_OnClick(w, x, y, button);
}
return false;
}
bool OnMouseEnter(widget w, int x, int y)
{
if (!IsLocalUsing3DGUI())
return false;
if(w.GetFlags() & WF_DISABLED)
return false;
if (IsMultiplayer())
RP_OnMouseEnter(w, x, y, false);
else
{
UniversalClassWithWidgetEvent("OnMouseEnter", this, w, x, y, -1);
MPSafe_OnMouseEnter(w, x, y);
}
return false;
}
bool OnMouseLeave(widget w, int x, int y)
{
if (!IsLocalUsing3DGUI())
return false;
if(w.GetFlags() & WF_DISABLED)
return false;
if (IsMultiplayer())
RP_OnMouseLeave(w, x, y, false);
else
{
UniversalClassWithWidgetEvent("OnMouseLeave", this, w, x, y, -1);
MPSafe_OnMouseLeave(w, x, y);
}
return false;
}
bool OnMouseButtonDown(widget w, int x, int y, int button)
{
if (!IsLocalUsing3DGUI())
return false;
cursor2DBtnPressed = NULL;
if(w.GetFlags() & WF_DISABLED)
return false;
if (Cursor_Enable && w.GetTypeName() == "ButtonWidget")
cursor2DBtnPressed = (ButtonWidget)w;
if (IsMultiplayer())
RP_OnMouseButtonDown(w, x, y, button, false);
else
{
UniversalClassWithWidgetEvent("OnMouseButtonDown", this, w, x, y, button);
MPSafe_OnMouseButtonDown(w, x, y, button);
}
return false;
}
bool OnMouseButtonUp(widget w, int x, int y, int button)
{
if (!IsLocalUsing3DGUI())
return false;
if(w.GetFlags() & WF_DISABLED)
return false;
if (Cursor_Enable && w.GetTypeName() == "ButtonWidget" && w == cursor2DBtnPressed)
OnClick(w, x, y, button);
if (IsMultiplayer())
RP_OnMouseButtonUp(w, x, y, button, false);
else
{
UniversalClassWithWidgetEvent("OnMouseButtonUp", this, w, x, y, button);
MPSafe_OnMouseButtonUp(w, x, y, button);
}
return false;
}
bool OnFocus(widget w, int x, int y)
{
return false;
}
bool OnKeyDown(widget w, int x, int y, int key)
{
return false;
}
bool OnKeyUp(widget w, int x, int y, int key)
{
return false;
}
bool OnKeyPress(widget w, int x, int y, int key)
{
return false;
}
bool OnEvent(int eventType, widget target, int parameter0, int parameter1)
{
return false;
}
}
//=================================================================
//base class for all game objects
//=================================================================
class GameObject extends CampaignObject
{
void GameObject();
void ~GameObject();
}
//=================================================================
// science target zone object
//=================================================================
class STargetZone extends GameObject
{
ScienceTarget owner;
TKOM_Entity worldSTZone;
vector coords;
float radius;
float height;
float completion;
int zonenum;
void STargetZone();
void ~STargetZone();
void SetOwnerPtr(ScienceTarget target);
void PrintData();
void UpdateWorldSTZones();
void WriteScienceTargetsToSCN(int file, local int level);
}
//=================================================================
// science target object. can own child targets
//=================================================================
class ScienceTarget extends GameObject
{
// Only for main science targets (missions)
Location owner;
VehicleObject vehicle; //assigned and launched vehicle. subtargets have set NULL! use GetVehicle() method to get assigned vehicle
string vehicleConfig;
string mission_title;
string mission_description;
string mission_result;
string mission_globalObjectives;
int mission_priority;
int mission_worth_major;
int mission_worth_minor;
bool mission_budgetGiven_major;
bool mission_budgetGiven_minor;
bool mission_budgetGiven_negligible;
bool mission_mobilityRequired;
void ClearMissionData();
void GenerateDefaultMissionData();
float GetMissionCompletion(int prioFilter);
vector GetMissionSubTgtCompletion(int prioFilter);
int GetMissionTargetsTotal(bool onlyEnabled, bool onlyIncomplete);
ScienceTarget GetMissionTargetByNum(ScienceTarget firstTgt, int countUp, int stNum, bool onlyEnabled, bool onlyIncomplete);
string GetMissionPriorityText();
ScienceTarget GetMissionParent(ScienceTarget sTarget);
int GetNumValidPresets();
int GetNumValidVehicles();
// Corresponds to the name of the vehicle that generated the mission (if set, indicates generated mission)
string mission_generatedByVehicleName;
void GenerateGeneratedMissionData(string vehicleName);
void ClearGeneratedMissionTasks(ScienceTarget ignoreST);
// For all
ScienceTarget parent;
string title;
string description;
int priority;
int worth;
bool enabled;
string onComplEnable;
int GetOnCompNum();
bool FindOnComp(string onCompST);
void AddOnComp(string onCompST);
void RemoveOnComp(string onCompST);
void RemoveOnCompST(string onCompST);
void EnableOnCompSTs(Location curLoc);
void ReCallSTOnComp(Location curLoc);
bool IsGlobalObjectiveAssigned(string globalObj); // Returns whether an input Global Objective is assigned to the mission
float GetGlobalObjectiveInstrumentRating(InstrumentDef inst); // Returns a total rating for an instrument used in a Global Objective mission
bool IsGlobalObjectiveColorCamRequired(); // Returns whether a color camera is required to complete the Global Objective mission
bool GetInMission(ScienceTarget target);
VehicleObject GetVehicle();
void SetVehicle(VehicleObject veh);
string GetIcon();
STargetZone zones[MAX_SCIENCE_TARGET_ZONES];
int zonesCount;
ScienceTarget childTargets[MAX_SCIENCE_TARGET_CHILDS];
int childTargetsCount;
void ScienceTarget();
void ~ScienceTarget();
bool IsParentedToTarget(ScienceTarget target);
void PassChildrenToParent(GameObject locSubEnt);
bool RemoveChildTarget(ScienceTarget target);
void RegisterChildTarget(ScienceTarget child);
ScienceTarget FindChildTarget(local string name, local bool recursive);
ScienceTarget FindChildTargetDuplicate(local string name, local bool recursive, int dupNum);
bool RemoveZone(STargetZone target);
STargetZone CreateZone();
void DestroyZones();
void SetEnabled(bool enable);
void UpdateSTVisualizers(bool show_sts, bool show_lnk, GameObject locSubEnt);
bool IsGenericType();
bool IsPhotoType();
bool IsAnalyzeType();
void PrintGenericData();
void PrintData();
float GetCompletion();
void ClearCompletion();
void GenerateDefaultData(vector pos, ScienceTarget ownEnt);
void DeleteWorldSTZones();
void DoAnalysis(TKOM_Entity vehicle, string instSubType, int physMat, string specMat, vector pos);
void DoPhoto(TKOM_Entity vehicle, int camNum, vector camPos, bool color);
void UpdateWorldSTZones();
void WriteScienceTargetsToSCN(int file, local int level);
void WriteScienceMissionToSCN(int file, string startAdd);
bool IsCurrentlyCompletable(); // Returns true if the player's tech matches, there are vehicles that can complete it
bool HasTechForTarget(bool recursive, int prioFilter, bool anyAtAllMode); // Returns true if the player has sufficient tech to complete the target
bool GetValidInstruments(string parts_types[], string parts_subtypes[], int parts_num, bool recursive, int prioFilter, bool anyAtAllMode); // Returns true if defined parts contain the required instruments for the STs
string GetWorthText();
string GetPriorityText();
}
//=================================================================
class ScienceTargetPhoto extends ScienceTarget
{
int minIncNum;
bool colorCameraReq;
bool IsGenericType();
void ScienceTargetPhoto();
bool IsPhotoType();
void PrintData();
void WriteScienceTargetsToSCN(int file, local int level);
bool IsGlobalObjectiveColorCamRequired();
bool GetValidInstruments(string parts_types[], string parts_subtypes[], int parts_num, bool recursive, int prioFilter, bool anyAtAllMode);
}
//=================================================================
class ScienceTargetAnalyze extends ScienceTarget
{
int physMat;
string specMat;
string specInst;
void ScienceTargetAnalyze();
bool IsGenericType();
bool IsAnalyzeType();
bool IsInstrumentInList(string instSubType);
int GetNumInstruments();
string GetInstrument(int numInList);
void PrintData();
void WriteScienceTargetsToSCN(int file, local int level);
float GetGlobalObjectiveInstrumentRating(InstrumentDef inst);
bool GetValidInstruments(string parts_types[], string parts_subtypes[], int parts_num, bool recursive, int prioFilter, bool anyAtAllMode);
}
//=================================================================
// scan result object
//=================================================================
int SCAN_CMD_VISIBLE = 1;
int SCAN_CMD_COLOR = 2;
int SCAN_CMD_TEXT = 3;
class ScanResult extends GameObject
{
int year;
int month;
int day;
int hour;
int minute;
int second;
string layoutFile;
bool viewed; // Set to true once the player has seen it
// widget, visible/color/text, value
string commandsList_widget[MAX_SCANS_CMDS];
int commandsList_type[MAX_SCANS_CMDS];
string commandsList_value[MAX_SCANS_CMDS];
int commandsCount;
void AddCommand(string cmdWStr, int cmdType, string cmdValStr);
widget LoadToWidget(widget tgtWidget); // load layout file, and perform commands
void ScanResult()
{
}
}
//=================================================================
// vehicle object.
//=================================================================
class VehicleObject extends GameObject
{
int Team; // Stores the team of the unit
int Store_ID; // Stores the ID of the unit (during saving etc)
string Owner_SteamID; // Stores the Steam ID of the owner of the unit
string Owner_SteamName; // Stores the Steam Name of the owner of the unit
vector CompatibilitySpawnMat[4]; // Matrix to teleport the unit to on compatibility spawn
void SetOwnerSteamID(string steamID)
{
Owner_SteamID = steamID;
}
void SetOwnerSteamName(string steamName)
{
Owner_SteamName = steamName;
}
bool NoStore; // If true, won't be stored in scenarios etc
bool NoCompatRespawn; // If true, will not be respawned to ensure compatibility (will use stored state only)
void NetSendData(PacketOutputAdapter output);
void NetReceiveData(PacketInputAdapter input);
CharacterObject followCharacter; // Stores which character the unit should follow
CharacterObject ToCharacterObject()
{
return NULL;
}
void OnAfterLoad();
// Stores the docking ports of the vehicle
int dockPort_dockedID[MAX_DOCKPORTS]; // ID of entity docked to port
int dockPort_portIndex[MAX_DOCKPORTS]; // Docking port index of the docked entity's port docked to port
float dockPort_undockForce[MAX_DOCKPORTS]; // Amount of force to apply to the docking port when undocking
float dockPort_undockTime[MAX_DOCKPORTS]; // Amount of time to apply undocking force to the docking port when undocking
float dockPort_currentUndockTime[MAX_DOCKPORTS]; // Current amount of undocking time (reduces over time, applying force)
int dockPort_part[MAX_DOCKPORTS]; // Vehicle part the docking port is on
vector dockPort_pos[MAX_DOCKPORTS];
vector dockPort_ang[MAX_DOCKPORTS];
float dockPort_Astress[MAX_DOCKPORTS]; // Angular stress above which the docking port disengages
float dockPort_Lstress[MAX_DOCKPORTS]; // Linear stress above which the docking port disengages
string dockPort_type[MAX_DOCKPORTS]; // Docking port type, for specific port type compatibility
int dockPort_num;
void ClearDockingPorts()
{
for (int i = 0; i < MAX_DOCKPORTS; i++)
{
dockPort_dockedID[i] = -1;
dockPort_portIndex[i] = -1;
dockPort_undockForce[i] = 0;
dockPort_undockTime[i] = 0;
dockPort_currentUndockTime[i] = 0;
dockPort_part[i] = -1;
dockPort_pos[i] = ZeroVec;
dockPort_ang[i] = ZeroVec;
dockPort_Astress[i] = -1;
dockPort_Lstress[i] = -1;
dockPort_type[i] = "";
}
dockPort_num = 0;
}
void AddDockingPort(int partNum, vector pos, vector ang, string docktype, float angStress, float linStress, float undockForce, float undockTime)
{
if (dockPort_num >= MAX_DOCKPORTS)
return;
dockPort_dockedID[dockPort_num] = -1;
dockPort_portIndex[dockPort_num] = -1;
dockPort_currentUndockTime[dockPort_num] = 0;
dockPort_undockForce[dockPort_num] = undockForce;
dockPort_undockTime[dockPort_num] = undockTime;
dockPort_part[dockPort_num] = partNum;
dockPort_pos[dockPort_num] = pos;
dockPort_ang[dockPort_num] = ang;
dockPort_Astress[dockPort_num] = angStress;
dockPort_Lstress[dockPort_num] = linStress;
dockPort_type[dockPort_num] = docktype;
dockPort_num++;
}
void SetDockingPort(int dockPortIndex, int partNum, vector pos, vector ang, string docktype, float angStress, float linStress, float undockForce, float undockTime)
{
dockPort_dockedID[dockPortIndex] = -1;
dockPort_portIndex[dockPortIndex] = -1;
dockPort_currentUndockTime[dockPortIndex] = 0;
dockPort_undockForce[dockPortIndex] = undockForce;
dockPort_undockTime[dockPortIndex] = undockTime;
dockPort_part[dockPortIndex] = partNum;
dockPort_pos[dockPortIndex] = pos;
dockPort_ang[dockPortIndex] = ang;
dockPort_Astress[dockPortIndex] = angStress;
dockPort_Lstress[dockPortIndex] = linStress;
dockPort_type[dockPortIndex] = docktype;
}
bool GetDocked(int dockPortIndex)
{
if (dockPort_dockedID[dockPortIndex] > 0)
return true;
else
return false;
}
void DockToPort(int otherID, int tgtPort, int myPort);
void UndockPort(local int myPort, bool applyUndockForce);
void UndockAll()
{
for (local int i = 0; i < dockPort_num; i++)
{
UndockPort(i, false);
}
}
// Stores the ladders of the vehicle
bool ladder_disabled[MAX_LADDERS];
vector ladder_pos_top[MAX_LADDERS];
vector ladder_pos_bottom[MAX_LADDERS];
vector ladder_ang_top[MAX_LADDERS];
vector ladder_ang_bottom[MAX_LADDERS];
vector ladder_hilite_up[MAX_LADDERS];
vector ladder_hilite_down[MAX_LADDERS];
string ladder_anim_up[MAX_LADDERS];
string ladder_anim_down[MAX_LADDERS];
int ladder_part[MAX_LADDERS];
int ladder_num;
void ClearLadders()
{
for (int i = 0; i < MAX_LADDERS; i++)
{
ladder_disabled[i] = false;
ladder_pos_top[i] = ZeroVec;
ladder_pos_bottom[i] = ZeroVec;
ladder_ang_top[i] = ZeroVec;
ladder_ang_bottom[i] = ZeroVec;
ladder_hilite_up[i] = ZeroVec;
ladder_hilite_down[i] = ZeroVec;
ladder_anim_up[i] = "";
ladder_anim_down[i] = "";
ladder_part[i] = -1;
}
ladder_num = 0;
}
void AddLadder(int partNum, vector pos_top, vector ang_top, vector pos_bottom, vector ang_bottom, vector hilite_up, vector hilite_down, string anim_up, string anim_down)
{
if (ladder_num >= MAX_LADDERS)
return;
ladder_disabled[ladder_num] = false;
ladder_pos_top[ladder_num] = pos_top;
ladder_pos_bottom[ladder_num] = pos_bottom;
ladder_ang_top[ladder_num] = ang_top;
ladder_ang_bottom[ladder_num] = ang_bottom;
ladder_hilite_up[ladder_num] = hilite_up;
ladder_hilite_down[ladder_num] = hilite_down;
ladder_anim_up[ladder_num] = anim_up;
ladder_anim_down[ladder_num] = anim_down;
ladder_part[ladder_num] = partNum;
ladder_num++;
}
void SetLadder(int ladderIndex, int partNum, vector pos_top, vector ang_top, vector pos_bottom, vector ang_bottom, vector hilite_up, vector hilite_down, string anim_up, string anim_down)
{
ladder_disabled[ladderIndex] = false;
ladder_pos_top[ladderIndex] = pos_top;
ladder_pos_bottom[ladderIndex] = pos_bottom;
ladder_ang_top[ladderIndex] = ang_top;
ladder_ang_bottom[ladderIndex] = ang_bottom;
ladder_hilite_up[ladderIndex] = hilite_up;
ladder_hilite_down[ladderIndex] = hilite_down;
ladder_anim_up[ladderIndex] = anim_up;
ladder_anim_down[ladderIndex] = anim_down;
ladder_part[ladderIndex] = partNum;
}
void EnableLadder(int ladderIndex, bool enable)
{
if (enable)
ladder_disabled[ladderIndex] = false;
else
ladder_disabled[ladderIndex] = true;
}
// Stores the passengers of the vehicle. Each slot corresponds to individual seats in the vehicle
CharacterObject passengers[MAX_PASSENGERS_PER_VEHICLE];
vector passengerSeat_pos[MAX_PASSENGERS_PER_VEHICLE];
vector passengerSeat_ang[MAX_PASSENGERS_PER_VEHICLE];
string passengerSeat_animDriver[MAX_PASSENGERS_PER_VEHICLE];
string passengerSeat_animDriver_In[MAX_PASSENGERS_PER_VEHICLE];
string passengerSeat_animDriver_Out[MAX_PASSENGERS_PER_VEHICLE];
string passengerSeat_animSit[MAX_PASSENGERS_PER_VEHICLE];
string passengerSeat_animSit_In[MAX_PASSENGERS_PER_VEHICLE];
string passengerSeat_animSit_Out[MAX_PASSENGERS_PER_VEHICLE];
int passengerSeat_part[MAX_PASSENGERS_PER_VEHICLE];
bool passengerSeat_driver[MAX_PASSENGERS_PER_VEHICLE];
bool passengerSeat_canSleep[MAX_PASSENGERS_PER_VEHICLE];
vector passengerSeatExit_pos[MAX_PASSENGERS_PER_VEHICLE];
vector passengerSeatExit_ang[MAX_PASSENGERS_PER_VEHICLE];
int passengerSeat_num;
int passengerSeat_CurrentDriver;
void ClearPassengerSeats()
{
passengerSeat_num = 0;
passengerSeat_CurrentDriver = -1;
for (int i = 0; i < MAX_PASSENGERS_PER_VEHICLE; i++)
{
passengers[i] = NULL;
passengerSeat_pos[i] = ZeroVec;
passengerSeat_ang[i] = ZeroVec;
passengerSeatExit_pos[i] = ZeroVec;
passengerSeatExit_ang[i] = ZeroVec;
passengerSeat_animDriver[i] = "";
passengerSeat_animDriver_In[i] = "";
passengerSeat_animDriver_Out[i] = "";
passengerSeat_animSit[i] = "";
passengerSeat_animSit_In[i] = "";
passengerSeat_animSit_Out[i] = "";
passengerSeat_part[i] = -1;
passengerSeat_driver[i] = false;
}
}
void AddPassengerSeat(bool driverSeat, bool canSleep, int partNum, vector pos, vector ang, string animDriver, string animDriverIn, string animDriverOut, string animSit, string animSitIn, string animSitOut, vector exitPos, vector exitAng)
{
if (passengerSeat_num >= MAX_PASSENGERS_PER_VEHICLE)
return;
passengerSeat_driver[passengerSeat_num] = driverSeat;
passengerSeat_canSleep[passengerSeat_num] = canSleep;
passengerSeat_pos[passengerSeat_num] = pos;
passengerSeat_ang[passengerSeat_num] = ang;
passengerSeat_animDriver[passengerSeat_num] = animDriver;
passengerSeat_animDriver_In[passengerSeat_num] = animDriverIn;
passengerSeat_animDriver_Out[passengerSeat_num] = animDriverOut;
passengerSeat_animSit[passengerSeat_num] = animSit;
passengerSeat_animSit_In[passengerSeat_num] = animSitIn;
passengerSeat_animSit_Out[passengerSeat_num] = animSitOut;
passengerSeat_part[passengerSeat_num] = partNum;
passengerSeatExit_pos[passengerSeat_num] = exitPos;
passengerSeatExit_ang[passengerSeat_num] = exitAng;
passengerSeat_num++;
}
void SetPassengerSeat(int seatIndex, bool driverSeat, bool canSleep, int partNum, vector pos, vector ang, string animDriver, string animDriverIn, string animDriverOut, string animSit, string animSitIn, string animSitOut, vector exitPos, vector exitAng)
{
passengerSeat_driver[seatIndex] = driverSeat;
passengerSeat_canSleep[seatIndex] = canSleep;
passengerSeat_pos[seatIndex] = pos;
passengerSeat_ang[seatIndex] = ang;
passengerSeat_animDriver[seatIndex] = animDriver;
passengerSeat_animDriver_In[seatIndex] = animDriverIn;
passengerSeat_animDriver_Out[seatIndex] = animDriverOut;
passengerSeat_animSit[seatIndex] = animSit;
passengerSeat_animSit_In[seatIndex] = animSitIn;
passengerSeat_animSit_Out[seatIndex] = animSitOut;
passengerSeat_part[seatIndex] = partNum;
passengerSeatExit_pos[seatIndex] = exitPos;
passengerSeatExit_ang[seatIndex] = exitAng;
}
CharacterObject GetDriver()
{
if (passengerSeat_CurrentDriver < 0)
return NULL;
CharacterObject result = passengers[passengerSeat_CurrentDriver];
return result;
}
int GetNextDriver()
{
for (int i = 0; i < passengerSeat_num; i++)
{
if (passengerSeat_driver[i] && passengers[i])
return i;
}
return -1;
}
bool GetVehicleSeatEmpty(int seatIndex)
{
if (passengers[seatIndex] == NULL)
return true;
return false;
}
int GetEmptyVehicleSeat()
{
for (int i = 0; i < passengerSeat_num; i++)
{
if (passengers[i] == NULL)
return i;
}
return -1;
}
void DisembarkAll();
Vehicle_Handler vehicleHandler; // Careful, only exists while in the vehicle's location!
bool GetIsLocallyControlled(); // Returns whether the unit is being controlled locally
Location owner;
ScienceTarget mission; //assigned mission
ScanResult scans[MAX_SCANS_PER_VEHICLE];
int scansCount;
Photo logoutPhoto;
Photo photos[MAX_PHOTOS_PER_VEHICLE];
int photosCount;
string scansQueue[MAX_SCANS_PER_VEHICLE]
int scansQueueSize;
string cfgFile; //vehicle spawned file
void StoreCFGPathName(string cfgPath)
{
cfgFile = cfgPath;
}
string defFile; //vehicle skeleton configuration file (for rovers etc)
string photosDirName; //folder name for photos
string mapIcon; //map icon image
string guiIcon; //gui icon image
string previewImage; //gui preview image
bool isMobile; // Whether the vehicle is mobile
bool isSpace; // Whether the vehicle is designed for use in space
bool isGround; // Whether the vehicle is designed for use on the ground
bool isCharacter; // Whether the unit is a character
bool isNetwork; // Whether the unit is network entity
bool isNotSelectable; // Whether the unit cannot be selected and controlled directly
float metersDriven; // Stores the total amount of meters the vehicle has driven
float metersDrivenSol; // Stores the total amount of meters the vehicle has driven this sol
int currentSol; // Stores the current sol number
float landing_totaltime; // Stores the total time that the vehicle descended for
float landing_manualtime; // Stores the total time that the player controlled the descent for
bool landing_landedOnce; // Stores whether the vehicle landed at least once
int interactionLayer; // Stores last interaction layer
bool ManualInputEnabled; // If true, the player may control the vehicle manually
// Variables that need serialization
// =============================================================================================
vector UnitMapMatrix[4]; // Matrix to use for the map panels (direction, position)
int CurrentPriPart; // The currently selected primary part
int CurrentSecPart; // The currently selected secondary part
int CurrentInstrument; // The currently selected part of type instrument
int CurrentHUDMode; // The currently active HUD mode: 0 = None, 1 = Camera, 2 = Instrument
int ReturnToHUDMode; // Stores the HUD mode for things like scan results, so that it returns you after closing them
int CurrentCamera; // The currently selected camera
int NightCamLEDPart; // Part number of the camera with enabled LEDs
bool SystemsActivated; // True when the vehicle systems should be activated (after landing)
bool LandingActivated; // True when the vehicle landing systems should be activated (after deploy from landing module)
bool HUDType; // Determines which HUD type should be used: 0 = Ground, 1 = Landing
bool NightVision; // True if night vision should be enabled
int ThermalVisionMode; // If greater than 0, thermal vision active
bool NightCamLEDs; // True if camera LEDs should be enabled
bool MouseControlPri; // If true, mouse controls primary system, if false, mouse controls secondary system
bool ConsoleControl; // If true, a set of commands is issued to the vehicle instead of direct control
vector LandingZone; // Target position to land at
vector ReentryZone; // Target position to start reentry in
vector ReentryVelocity; // Target velocity to start reentry with
vector ReentryOffsetPos; // Target position offset to start reentry with
vector ReentryOffsetAng; // Target angles offset to start reentry with
float PowerLevel; // Stores the amount of power the vehicle has available
float LowPowerNotifiedLevel; // Stores whether the vehicle notified the player that it has low power
bool LandingManual; // Stores if the player is manually controlling the descent
// Custom set waypoint and direction (for instructing the robotic arm etc)
vector CustomWaypoint;
vector CustomDir;
// Joints
vector joints_angles[VEHICLE_MAXJOINTS];
vector joints_limits_lo[VEHICLE_MAXJOINTS];
vector joints_limits_hi[VEHICLE_MAXJOINTS];
bool joints_isLODed[VEHICLE_MAXJOINTS];
int joints_type[VEHICLE_MAXJOINTS];
int joints_part1[VEHICLE_MAXJOINTS]; // Parent part number
int joints_part2[VEHICLE_MAXJOINTS]; // Child part number
float joints_Astress[VEHICLE_MAXJOINTS]; // Maximum angular stress before joint breaks
float joints_Lstress[VEHICLE_MAXJOINTS]; // Maximum linear stress before joint breaks
string joints_breakPtcSnd[VEHICLE_MAXJOINTS]; // Particle and sound effect to spawn when the joint breaks
int joints_FXIndex[VEHICLE_MAXJOINTS]; // Local index of the vehicle FX to use for effects (break etc)
float joints_pwrdrain[VEHICLE_MAXJOINTS]; // Stores how much the joint drains power
bool joints_noDelete[VEHICLE_MAXJOINTS]; // If set to true, the joint will not be deleted by breakage etc
int joints_num; // Stores the amount of joints
// Collision blockers
int blocks_part1[VEHICLE_MAXBLOCKS]; // Part 1 number
int blocks_part2[VEHICLE_MAXBLOCKS]; // Part 2 number
bool blocks_noDelete[VEHICLE_MAXBLOCKS]; // If set to true, the blocker will not be deleted by breakage etc
int blocks_num; // Stores the amount of collision blockers
// Inventories
Inventory inventories[INVENTORY_PEROBJECT_MAX]; // Stores each inventory pointer
int inventories_partNum[INVENTORY_PEROBJECT_MAX]; // Stores part index the inventory is bound to
int inventoriesNum; // Store amount of inventories
void DeleteInventoriesItemsScripts();
void LoadInventoriesItemsScripts();
void RestoreInventoriesItemsIDs();
void DestroyInventories();
Inventory FindInventoryByName(string invName);
Inventory FindInventoryByPartNum(int pNum);
bool CreateInventory(int index, string invName, int partNum, string layout, string hiText, string hiImg, int numSlots, string slotTypes[]);
void InventoriesOnEvent(string eventName);
void InventoriesOnEventWithForce(string eventName, vector pos, vector force);
void InventoriesOnEventWithEntity(string eventName, _entity ent);
void InventoriesOnEventWithInt(string eventName, int input);
void InventoriesOnEventWithFloat(string eventName, float input);
void InventoriesOnFrame();
void InventoriesOnPostFrame();
void InventoriesOnSimulate();
// Parts
float parts_pwrdrain[VEHICLE_MAXPARTS]; // Stores whether each part is draining power
float parts_damage[VEHICLE_MAXPARTS]; // Stores the damage of each part
int parts_tough[VEHICLE_MAXPARTS]; // Stores the toughness level of each part
float parts_mass[VEHICLE_MAXPARTS]; // Stores the mass of each part
string parts_models[VEHICLE_MAXPARTS]; // Stores the model string for each part
string parts_types[VEHICLE_MAXPARTS]; // Stores the type of each part, such as "Wheel", "Camera"
string parts_subtypes[VEHICLE_MAXPARTS]; // Stores the sub-type of each part, such as "T_Attitude", "T_Hover"
string parts_title[VEHICLE_MAXPARTS]; // Stores the display name of the part, such as "6-Wheel Drive"
string parts_detailsTitle[VEHICLE_MAXPARTS]; // Stores the map's Vehicle Details name
string parts_detailsStatus[VEHICLE_MAXPARTS]; // Stores the map's Vehicle Details status
vector parts_pos[VEHICLE_MAXPARTS]; // Stores the position of the parts
vector parts_ang[VEHICLE_MAXPARTS]; // Stores the angles of the parts
vector parts_wmat0[VEHICLE_MAXPARTS]; // Matrix[0] of the part in the world
vector parts_wmat1[VEHICLE_MAXPARTS]; // Matrix[1] of the part in the world
vector parts_wmat2[VEHICLE_MAXPARTS]; // Matrix[2] of the part in the world
vector parts_wmat3[VEHICLE_MAXPARTS]; // Matrix[3] of the part in the world
vector parts_velLin[VEHICLE_MAXPARTS]; // Linear velocity of the part in the world
vector parts_velAng[VEHICLE_MAXPARTS]; // Angular velocity of the part in the world
vector parts_genVec[VEHICLE_MAXPARTS]; // Generic vector in part for use in controllers
vector parts_genVec2[VEHICLE_MAXPARTS]; // 2nd Generic vector in part for use in controllers
vector parts_genVec3[VEHICLE_MAXPARTS]; // 3rd Generic vector in part for use in controllers
vector parts_genVec4[VEHICLE_MAXPARTS]; // 4th Generic vector in part for use in controllers
vector parts_genVec5[VEHICLE_MAXPARTS]; // 5th Generic vector in part for use in controllers
vector parts_genVec6[VEHICLE_MAXPARTS]; // 6th Generic vector in part for use in controllers
string parts_conPtcSnd[VEHICLE_MAXPARTS]; // Particle and sound effect to spawn when the part hits the ground
int parts_storedParent[VEHICLE_MAXPARTS]; // The parent of the part as per save
int parts_num; // Stores the amount of parts
string GenStrings[MAX_VEHICLES_GENSTRINGNUM]; // Generic strings
string ctrl_types[CONTROL_VEHICLEMAX]; // Defines which registered part types can be selected
int ctrl_num; // Stores the amount of controllable types
int ctrlbase_parts[CONTROL_VEHICLEMAX]; // Defines which registered part types are considered a "base" (in selecting next parts etc)
int ctrlbase_num; // Stores the amount of base parts
// Static part connections
int statcons_part1[VEHICLE_MAXPARTS]; // Parent
int statcons_part2[VEHICLE_MAXPARTS]; // Child
int statcons_num; // Stores the amount of static part connections
// Controller script paths
string script_Path[CONTROL_VEHICLEMAX];
int script_num; // Stores the amount of controller scripts
// Vehicle switch tab variables
int tabs_opened; // Read from the campaign to determine which tab is opened. 0 = closed, 1 = Nav, 2 = Inf, 3 = Vis, 4 = Ctr
bool tabs_update; // Read from the campaign to determine whether to update the tabs
bool tabs_closed; // Read from controllers to know whether or not the tabs frame should be hidden (arcade GUI)
float tabs_framepos; // Stores the offset position percentage (0 - 1) of the tabs window (arcade GUI)
int tabs_nav_WPDist; // Stores the waypoint distance filter setting
int tabs_nav_WPPrio; // Stores the waypoint priority filter setting
int tabs_nav_WPMis; // Stores the waypoint mission filter setting
int tabs_nav_WPTask; // Stores the waypoint mission task filter setting
bool tabs_nav_SatOnline; // Stores whether the vehicle is connected to the location's satellite
// Vehicle camera display variables
int cams_list[CAMS_MAX];
bool cams_online[CAMS_MAX];
bool cams_closed; // Read from controllers to know whether or not the GUI PIP cameras should be hidden
float cams_framepos; // Stores the offset position percentage (0 - 1) of the GUI PIP camera window
int cams_mainMode; // The vehicle camera mode, 0 = 1st, 1 = 3rd (global orientation), 2 = 3rd (vehicle orientation)
vector cams_3rdAngles; // Stores the offset angles of the world oriented 3rd person camera
vector cams_3rdAngles2; // Stores the offset angles of the object oriented 3rd person camera
vector cams_3rdPosition; // Stores the offset position of the world oriented 3rd person camera
vector cams_3rdPosition2; // Stores the offset position of the object oriented 3rd person camera
int cams_3rdPart; // The current part being used for 3rd person camera
//Modular GUI variables
bool cams_visible; // Read from controllers to know whether or not the cameras panel should be hidden
bool inst_visible; // Read from controllers to know whether or not the instruments panel should be hidden
bool ctrl_visible; // Read from controllers to know whether or not the controls panel should be hidden
bool loc_visible; // Read from controllers to know whether or not the location info panel should be hidden
bool pwr_visible; // Read from controllers to know whether or not the power levels panel should be hidden
float camHUD_focalPct[CAMS_FOCALPOINTS]; // Stores the last focal trace percentages for each point
// Vehicle instrument display variables
int inst_analyze_physMat[VEHICLE_MAXPARTS]; // When an instrument takes a sample, it stores the physical material here
string inst_analyze_specMat[VEHICLE_MAXPARTS]; // When an instrument takes a sample, it stores the specific material shader here
// Space Agency mission variables (for history)
int Agency_MisCost; // Stores how much each mission launched cost
int Agency_VehicleProfit; // How much money the vehicle has made for the agency in $K
int Agency_VehicleMissionsCompleted_Major; // How many major missions the vehicle has completed
int Agency_VehicleMissionsCompleted_Minor; // How many minor missions the vehicle has completed
int Agency_VehicleMissionsCompleted_Negligible; // How many negligible missions the vehicle has completed
int DayZero_Year;
int DayZero_Month;
int DayZero_Day;
int DayZero_Hour;
int DayZero_Minute;
int DayZero_Second;
void SetDayZero();
float GetMissionDayCount(); // Returns the total number of days (converted to local planet day length) the mission has been active for since landing
float traversePath[1024];
void VehicleObject();
void ~VehicleObject();
ScienceTarget GetMission();
VehicleDef FindDefinition();
void SetMission(ScienceTarget mis);
void SetOwnerPtr(Location location);
void Preinit(VehicleObject vehicle);
void SetReentryPos(vector pos);
void SetDefinitionFile(string fileName);
void ClearData();
void CopyDataFromDefinition(VehicleDef def);
bool CanCompleteMission(ScienceTarget stMission, Location missionLocation);
string GetStatusText();
bool CanAddScan();
bool AddScan(ScanResult scan);
ScanResult AddNewScan(string scanName);
ScanResult FindScan(string name);
void DestroyScans();
bool noPhotos; // If true, the vehicle will not create any photo files
bool AddPhoto(Photo photo);
Photo CreateScreenshotPhoto(string photoName, int photoWidth, int photoHeight);
Photo AddScreenshotPhoto(int camNum);
Photo MakeLogoutPhoto();
Photo FindPhoto(string name);
int GetPhotoIndex(Photo photo);
int GetValidPhotosCount();
void DestroyPhotos(bool destroyFiles);
void DestroyPhoto(Photo photo, bool destroyFile);
void DestroyLogoutPhoto(bool destroyFile);
void DestroyPhotoFile(string filePath);
// Vehicle log
string LogEntries[MAX_VEHICLES_LOG_ENTRIES];
string LogDate[MAX_VEHICLES_LOG_ENTRIES];
int LogEntry_Cur;
void ClearLogEntries();
void AddLogEntry(string logEntry);
// Vehicle current commands
string CurrentCommandParsed[MAX_VEHICLES_COMMAND_PARTS];
int CurrentCommandParsed_Num;
int CurrentCommandValidParts; // How many parts of the command are valid
int CurrentCommandRequiredParts; // How many parts are needed for the command
bool CurrentCommandRequiredPoint; // Whether a custom set point is required for the command
string CurrentCommand;
void ClearCurrentCommand();
void SetCurrentCommand(string command);
// Vehicle packet commands list
string PacketCommands[MAX_VEHICLES_COMMANDS_PACKET];
vector PacketCommands_CustomPos[MAX_VEHICLES_COMMANDS_PACKET];
vector PacketCommands_CustomDir[MAX_VEHICLES_COMMANDS_PACKET];
int PacketCommands_Cur;
void ClearPacketCommands();
void AddPacketCommand(string command, vector commandPos, vector commandDir);
// Vehicle commands list
string ExecuteCommandParsed[MAX_VEHICLES_COMMAND_PARTS];
int ExecuteCommandParsed_Num;
int ExecuteCommandParsed_Index;
string Commands[MAX_VEHICLES_COMMANDS];
string CommandsDate[MAX_VEHICLES_COMMANDS];
vector Commands_CustomPos[MAX_VEHICLES_COMMANDS];
vector Commands_CustomDir[MAX_VEHICLES_COMMANDS];
int Commands_Cur;
float CommandPerforming_Pct; // Percentage completion of the command being currently executed
float CommandPerforming_WaitTime; // Amount in seconds to wait between performing the next action
void ClearCommands();
void AddCommand(string command, vector commandPos, vector commandDir);
void RemoveCommand(int index);
void CommandComplete(bool successful);
void CopyPacketCommandsToCommands();
void ClearExecuteCommand();
void SetExecuteCommand(int index);
void UpdateCommandSequence(float timeSlice);
bool IsCommandWithinDate(int index, int year, int month, int day, int hour, int minute, int second); // Returns true if the current date + OWLT is larger than the command's date
void GetCommandDate(int index, int date[6]);
int WaitCommand_DateStorage[7]; // Stores the date the current 'WAIT' command started (for time skip etc)
bool CommandsShowHelp; // If true, the help panel for commands should be open
string GenerateCampaignName();
void SetName(string nameStr)
{
name = nameStr;
}
/** GENERATED MISSION RELATED **/
ScienceTarget generatedMission; // Mission that is generated as the vehicle moves
bool genMis_AllowGenerate; // If true, allows mission generation
float genMis_NoMisCheckInterval; // Stores the current interval in checking for new missions if none exist
void UpdateGeneratedMission(float fTimeslice, vector pos);
// Unit data fillers
void FillData_CtrlScript(string csdata0[], string csdata1[]); // Vehicle controller script data filling
void FillData_CtrlBase(int cbdata0[]); // Vehicle base part data filling
void FillData_DockPorts(int numPorts, int dpdata0[], vector dpdata1[], vector dpdata2[], float dpdata3[], float dpdata4[], string dpdata5[], float dpdata6[], float dpdata7[]); // Vehicle docking port filling
void FillData_DockPortsDocked(int dpdata0[], int dpdata1[]); // Vehicle docking ports' docked data filling
void FillData_Joints(vector jdata0[], vector jdata1[], vector jdata2[], int jdata3[], int jdata4[], int jdata5[], float jdata6[], float jdata7[], string jdata8[], float jdata9[], bool jdata10[], bool jdata11[]); // Vehicle joint data filling
void FillData_Blocks(int bdata0[], int bdata1[], bool bdata2[]); // Vehicle collision blocker data filling
void FillData_Parts(float pdata0[], int pdata1[], float pdata2[], string pdata3[], string pdata4[], string pdata5[], vector pdata6[], vector pdata7[], vector pdata8[], vector pdata9[], vector pdata10[]); // Vehicle part data filling 1/3
void FillData_Parts2(vector pdata11[], vector pdata12[], vector pdata13[], vector pdata14[], vector pdata15[], vector pdata16[], vector pdata17[], vector pdata18[], vector pdata19[], string pdata20[], int pdata21[]); // Vehicle part data filling 2/3
void FillData_Parts3(string pdata22[]); // Vehicle part data filling 3/3
void FillData_Inst(int idata1[], string idata2[]); // Vehicle instrument data filling
void FillData_StatCon(int cdata0[], int cdata1[]); // Vehicle static connections filling
void FillData_Inventories(string dataInvNames[INVENTORY_PEROBJECT_MAX], int dataPartIndex[INVENTORY_PEROBJECT_MAX], string dataLayout[INVENTORY_PEROBJECT_MAX], string dataHiTxt[INVENTORY_PEROBJECT_MAX], string dataHiImg[INVENTORY_PEROBJECT_MAX], int dataSlotNum[INVENTORY_PEROBJECT_MAX], string dataSlotTypes[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX]); // Vehicle inventory definitions data filling
void FillData_StoredInventoryItems(string dataItmTitles[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmDescs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmImgs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmScripts[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmCFGs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmMdls[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmRmps[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmFX[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], float dataItmMass[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmVldSlts[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], int dataItmGenInts[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], float dataItmGenFloats[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmGenVecs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmGenStrs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX]); // Vehicle stored inventory items data filling
void FillData_GenString(string strdata[]);
}
//=================================================================
// character object.
//=================================================================
const int CHAR_MOVESTATE_STANDING = 0;
const int CHAR_MOVESTATE_CROUCHING = 1;
const int CHAR_MOVESTATE_SWIMMING = 2;
const int CHAR_MOVESTATE_FLOATING = 3;
const int CHAR_MOVESTATE_FREEFALL = 4;
const int CHAR_MOVESTATE_SEATED = 5;
const int CHAR_MOVESTATE_DEAD = 6;
const float CHAR_LUNGSAIR_MAX = 60;
const float CHAR_HEARTRATE_DEFAULT = 70;
const float CHAR_HEARTRATE_ACTIVE = 105;
const float CHAR_HEARTRATE_MAX = 190;
const float CHAR_RESPRATE_DEFAULT = 15;
const float CHAR_RESPRATE_MAX = 60;
const float CHAR_METABOLISM_SCALEMIN = 0.5;
const float CHAR_METABOLISM_SCALEMAX = 1.5;
const float CHAR_METABOLISM_DEFAULTRATE = 1;
const float CHAR_METABOLISM_CALORIESWHENACTIVE = 980;
const float CHAR_METABOLISM_AVGDAILYCALORIES = 2100;
const float CHAR_METABOLISM_AVGDAILYVITAMINS = 5;
const float CHAR_METABOLISM_AVGDAILYWATER = 2.8;
const float CHAR_METABOLISM_AVGBODYTEMP = 37;
const float CHAR_METABOLISM_AVGSLEEP = 8;
const float CHAR_METABOLISM_AVGRADIATION = 0.1;
const float CHAR_METABOLISM_AVGDAILYRADIATIONLOSS = 0.15;
const float CHAR_METABOLISM_DEATHCALORIES = -100;
const float CHAR_METABOLISM_DEATHVITAMINS = -1;
const float CHAR_METABOLISM_DEATHWATER = -0.25;
const float CHAR_METABOLISM_DEATHTEMPERATURE_HIGH = 42.5;
const float CHAR_METABOLISM_DEATHTEMPERATURE_LOW = 35.2;
const float CHAR_METABOLISM_DEATHRADIATION = 3;
const float CHAR_METABOLISM_DEATHSLEEP = -16;
const float CHAR_METABOLISM_DANGERCALORIES = 200;
const float CHAR_METABOLISM_DANGERVITAMINS = 1;
const float CHAR_METABOLISM_DANGERWATER = 0.25;
const float CHAR_METABOLISM_DANGERTEMPERATURE_HIGH = 39.7;
const float CHAR_METABOLISM_DANGERTEMPERATURE_LOW = 35.7;
const float CHAR_METABOLISM_DANGERRADIATION = 1.5;
const float CHAR_METABOLISM_DANGERSLEEP = -8;
const float CHAR_METABOLISM_LOWCALORIES = 800;
const float CHAR_METABOLISM_LOWVITAMINS = 3;
const float CHAR_METABOLISM_LOWWATER = 0.75;
const float CHAR_METABOLISM_LOWSLEEP = 0;
const float CHAR_METABOLISM_WARNTEMPERATURE_HIGH = 37.8;
const float CHAR_METABOLISM_WARNTEMPERATURE_LOW = 36.7;
const float CHAR_METABOLISM_WARNRADIATION = 0.5;
const float CHAR_METABOLISM_MAXCALORIES = 2200;
const float CHAR_METABOLISM_MAXVITAMINS = 5;
const float CHAR_METABOLISM_MAXWATER = 2;
const float CHAR_METABOLISM_MAXSLEEP = 8;
const int CHAR_CURSORINFO_NULL = 0;
const int CHAR_CURSORINFO_HIGHLIGHTED = 1;
const int CHAR_CURSORINFO_HELD = 2;
const int CHAR_CURSORMASS_NORMAL = 0;
const int CHAR_CURSORMASS_HEAVY = 1;
const int CHAR_CURSORMASS_IMMOVABLE = 2;
const int CHAR_CURSOROBJECT_OBJECT = 0;
const int CHAR_CURSOROBJECT_VEHICLEDOORDRIVE = 1;
const int CHAR_CURSOROBJECT_VEHICLEDOORSIT = 2;
const int CHAR_CURSOROBJECT_VEHICLESLEEP = 3;
const int CHAR_CURSOROBJECT_VEHICLEACT = 4;
const int CHAR_CURSOROBJECT_BUILDBLOCKDYN = 5;
const int CHAR_CURSOROBJECT_BUILDBLOCKSTC = 6;
const int CHAR_CURSOROBJECT_BUILDBLOCKACT = 7;
const int CHAR_CURSOROBJECT_BUILDBLOCKSIT = 8;
const int CHAR_CURSOROBJECT_BUILDBLOCKGETUP = 9;
const int CHAR_CURSOROBJECT_BUILDBLOCKSLEEP = 10;
const int CHAR_CURSOROBJECT_RAGDOLL = 11;
const int CHAR_CURSOROBJECT_LADDER = 12;
const int CHAR_STANCE_UPRIGHT = 0;
const int CHAR_STANCE_CROUCH = 1;
class CharacterObject extends VehicleObject
{
/**
* NOTE:
*
* Data that needs to be sent on NetObjectInitSend for characters
* is in scripts/entities/VehicleHandlerFuncs.h, under the functions:
*
* void Vehicle_Handler::OnNetObjectAfterInitSend(PacketOutputAdapter output)
* void Vehicle_Handler::OnNetObjectAfterInitReceived(PacketInputAdapter input)
**/
widget w3dHUDRoot; // Only valid while the 3D HUD is shown!!!
// Used when the character is sitting/sleeping in a vehicle seat/bed
VehicleObject inVehicle; // Stores which vehicle the character is in
int inVehicleSeat; // Stores which vehicle seat the character is in
// Used when the character is sitting/sleeping in a building block
int inBlockID; // Stores which building block the character is sitting on
int inBlockSeat; // Stores which seat the character is sitting on in the building block
vector ViewBob; // Stores the viewbob for the 3 axes
vector ViewTarget; // Stores the target point the camera should try to aim at
float BodyYaw; // Stores the yaw of the body relative to the collider
vector HeadAngles; // Stores the angles of the character's head
int Ragdoll_ID; // If above 0, the character is linked to the ragdoll with this ID
bool GetInRagdoll()
{
if (Ragdoll_ID > 0)
return true;
else
return false;
}
float Survival_MetabolismRate; // Stores the rate of metabolism in scale form (less active characters have a lower value etc)
float Survival_Calories; // Stores the amount of calories in the body
float Survival_Vitamins; // Stores the amount of vitamins in the body (generalized as one value for all required vitamins)
float Survival_Water; // Stores the amount of water in the body in litres
float Survival_Temperature; // Stores the body temperature in Celsius
float Survival_Sleep; // Stores how many hours the character has slept
float Survival_Radiation; // Stores how much radiation the character has been exposed to in Sieverts
// Defaults survival element values
void SurvivalDefaults()
{
Survival_MetabolismRate = CHAR_METABOLISM_DEFAULTRATE;
Survival_Calories = CHAR_METABOLISM_MAXCALORIES;
Survival_Vitamins = CHAR_METABOLISM_MAXVITAMINS;
Survival_Water = CHAR_METABOLISM_MAXWATER;
Survival_Temperature = CHAR_METABOLISM_AVGBODYTEMP;
Survival_Sleep = CHAR_METABOLISM_AVGSLEEP;
Survival_Radiation = CHAR_METABOLISM_AVGRADIATION;
}
float AddCalories(float amount) // returns how much was added
{
float result = Survival_Calories;
Survival_Calories += amount;
if (Survival_Calories > CHAR_METABOLISM_MAXCALORIES)
Survival_Calories = CHAR_METABOLISM_MAXCALORIES;
result = Survival_Calories - result;
return result;
}
float AddVitamins(float amount) // returns how much was added
{
float result = Survival_Vitamins;
Survival_Vitamins += amount;
if (Survival_Vitamins > CHAR_METABOLISM_MAXVITAMINS)
Survival_Vitamins = CHAR_METABOLISM_MAXVITAMINS;
result = Survival_Vitamins - result;
return result;
}
float AddWater(float amount) // returns how much was added
{
float result = Survival_Water;
Survival_Water += amount;
if (Survival_Water > CHAR_METABOLISM_MAXWATER)
Survival_Water = CHAR_METABOLISM_MAXWATER;
result = Survival_Water - result;
return result;
}
float AddSleep(float amount) // returns how much was added
{
float result = Survival_Sleep;
Survival_Sleep += amount;
if (Survival_Sleep > CHAR_METABOLISM_MAXSLEEP)
Survival_Sleep = CHAR_METABOLISM_MAXSLEEP;
result = Survival_Sleep - result;
return result;
}
int Stance; // Stores the character's desired stance (crouching, standing, etc)
float Health; // Stores the current health of the character
float HeartBPM; // Stores the current heart rate in beats per minute of the character
float RespBPM; // Stores the current respiratory rate in breaths per minute of the character
float StunnedTime; // Stores the stunned time
float DeadTime; // Stores how long the character is dead for
float LungsAirTime; // Stores how much air in seconds the character has in his lungs (for underwater breathing etc)
string CurrentAnimation; // Stores the path to the current animation
string CustomAnimation; // Stores the path to the custom animation
bool CustomAnimMustComplete; // If true, the animation needs to be finished even if dead etc
bool CustomAnimationSet; // If true, the animation needs to be finished before being able to move etc
bool CustomAnimNoMove; // If true, then the character cannot move while playing the custom animation
bool CustomAnimLockView; // If true, then the character's view is locked while playing the animation
float CustomAnimationSpeed; // Stores how fast the custom animation plays
float CustomAnimationFade; // Stores how fast the custom animation fades
float CustomAnimFrame; // Stores the frame the current custom animation is in
bool noViewFocus; // Stores whether the character may zoom using the focus key
bool noMovement; // Stores whether the character may move around
bool noInventoryToggle; // Stores whether the character may open/close his inventory
int MovementState; // Stores the current movement state
int CursorInfoType; // Stores the current cursor info (whether holding an object, throwing, etc)
int CursorInfoMass; // Stores the current cursor object mass type (too heavy etc)
int CursorInfoObject; // Stores the current cursor object type (door, panel, etc)
string CursorInfoText; // Stores the text to display for the current object
string CursorInfoImage; // Stores the image to display for the current object
float CursorInfoWeight; // Stores the current cursor object weight
int HoldObjectID; // Stores the ID number of the currently held object
int HoldObjectSubID; // Stores an additional ID number for the currently held object (vehicle part index)
int TraceObjectID; //Stores the ID number of the currently traced object
int TraceObjectSubID; // Stores an additional ID number for the currently traced object (vehicle part index)
bool ToolEquipped; // Stores whether the character had his tool equipped
int ToolPartIndex; // Stores the index of the tool part (for controllers etc)
InventoryItemObject ToolItem; // Stores the currently selected tool (for controllers etc)
string GenerateCampaignName();
CharacterObject ToCharacterObject()
{
return this;
}
// Returns whether the character is allowed to move
bool CanMove()
{
if (MovementState == CHAR_MOVESTATE_FLOATING)
return false;
if (MovementState == CHAR_MOVESTATE_DEAD)
return false;
if (CustomAnimationSet && CustomAnimNoMove)
return false;
if (noMovement)
return false;
return true;
}
void ClearCustomAnimation()
{
CustomAnimFrame = 0;
CustomAnimationSet = false;
CustomAnimation = "";
CustomAnimationSpeed = 0;
CustomAnimationFade = 0;
CustomAnimMustComplete = false;
CustomAnimNoMove = false;
CustomAnimLockView = false;
}
// Sets a custom animation to play from start to finish (during which nothing else can be done)
void SetCustomAnimation(string animPath, float tgtAnimSpeed, float tgtAnimFadeSpeed, bool noMove, bool mustComplete, bool lockView)
{
CustomAnimFrame = 0;
CustomAnimationSet = true;
CustomAnimation = animPath;
CustomAnimationSpeed = tgtAnimSpeed;
CustomAnimationFade = tgtAnimFadeSpeed;
CustomAnimMustComplete = mustComplete;
CustomAnimNoMove = noMove;
CustomAnimLockView = lockView;
}
void SetCursorInfoDisplay(string objTitle, string objImg)
{
CursorInfoText = objTitle;
CursorInfoImage = objImg;
}
bool CanBoardVehicleSeat(int seatIndex, VehicleObject vehicle)
{
return vehicle.GetVehicleSeatEmpty(seatIndex);
}
void BoardVehicleSeat(int seatIndex, VehicleObject vehicle)
{
if (vehicle.passengers[seatIndex] == NULL)
{
if (vehicle.passengerSeat_CurrentDriver == -1 && vehicle.passengerSeat_driver[seatIndex])
vehicle.passengerSeat_CurrentDriver = seatIndex;
vehicle.passengers[seatIndex] = this;
inVehicle = vehicle;
inVehicleSeat = seatIndex;
}
}
int GetFreeVehicleSeat(VehicleObject vehicle)
{
return vehicle.GetEmptyVehicleSeat();
}
void DisembarkVehicle()
{
if (inVehicle)
{
inVehicle.passengers[inVehicleSeat] = NULL;
if (inVehicle.passengerSeat_CurrentDriver == inVehicleSeat)
inVehicle.passengerSeat_CurrentDriver = inVehicle.GetNextDriver();
inVehicle = NULL;
inVehicleSeat = -1;
}
}
void BoardBBlockSeat(int seatIndex, _entity bblockBase);
void DisembarkBBlock();
void EnterBBlockSeat(_entity bblockBase, int reachSeat);
bool IsPassenger()
{
if (!inVehicle || inVehicleSeat == -1 || inVehicle.passengerSeat_CurrentDriver == inVehicleSeat)
return false;
return true;
}
bool IsDriver()
{
if (!inVehicle || inVehicleSeat == -1 || !inVehicle.passengerSeat_driver[inVehicleSeat] || inVehicle.passengerSeat_CurrentDriver != inVehicleSeat)
return false;
return true;
}
bool CanSleepInSeat();
void EnterCar(VehicleObject vehicle, int reachSeat)
{
HoldObjectID = 0;
HoldObjectSubID = 0;
TraceObjectID = 0;
TraceObjectSubID = 0;
BoardVehicleSeat(reachSeat, vehicle);
CursorInfoType = CHAR_CURSORINFO_NULL;
MovementState = CHAR_MOVESTATE_SEATED;
}
bool SlotHighlight_Ground[INVENTORY_SLOTS_MAX];
bool SlotHighlight_Held;
void ClearAdditionalSlotHighlights()
{
SlotHighlight_Held = false;
for (int i = 0; i < INVENTORY_SLOTS_MAX; i++)
{
SlotHighlight_Ground[i] = false;
}
}
void SetGroundSlotHighlight(int index, bool enable)
{
SlotHighlight_Ground[index] = enable;
}
void SetHeldSlotHighlight(bool enable)
{
SlotHighlight_Held = enable;
}
void CharacterObject();
void ~CharacterObject();
}
//=================================================================
// ragdoll object.
//=================================================================
class RagdollObject extends GameObject
{
Location owner;
Ragdoll_Handler ragdollHandler; // Careful, only exists while in the ragdoll's location!
int Store_ID; // Stores the ID of the ragdoll (during saving etc)
int Store_OwnerID; // Stores the ID of the unit that owns the ragdoll (during saving etc)
bool NoStore; // If true, won't be stored in scenarios etc
bool isNetwork; // Whether the ragdoll is a network entity
int interactionLayer; // Stores last interaction layer
vector CompatibilitySpawnMat[4]; // Matrix to teleport the ragdoll to on compatibility spawn
void NetSendData(PacketOutputAdapter output);
void NetReceiveData(PacketInputAdapter input);
string cfgFile; //ragdoll spawned file
void StoreCFGPathName(string cfgPath)
{
cfgFile = cfgPath;
}
// Script path
string scriptPath;
// Joints
vector joints_angles[RAGDOLL_MAXJOINTS];
vector joints_limits_lo[RAGDOLL_MAXJOINTS];
vector joints_limits_hi[RAGDOLL_MAXJOINTS];
float joints_spring_stiff[RAGDOLL_MAXJOINTS];
float joints_spring_damp[RAGDOLL_MAXJOINTS];
int joints_part1[RAGDOLL_MAXJOINTS]; // Parent part number
int joints_part2[RAGDOLL_MAXJOINTS]; // Child part number
int joints_num; // Stores the amount of joints
// Collision blockers
int blocks_part1[RAGDOLL_MAXBLOCKS]; // Part 1 number
int blocks_part2[RAGDOLL_MAXBLOCKS]; // Part 2 number
int blocks_num; // Stores the amount of collision blockers
// Generic variables
float GenFloats[RAGDOLL_GENVARS];
int GenInts[RAGDOLL_GENVARS];
vector GenVecs[RAGDOLL_GENVARS];
string GenStrings[RAGDOLL_GENVARS];
// Parts
float parts_mass[RAGDOLL_MAXPARTS]; // Stores the mass of each part
string parts_models[RAGDOLL_MAXPARTS]; // Stores the model string for each part
string parts_name[RAGDOLL_MAXPARTS]; // Stores the name of each part, such as "Torso"
bool parts_static[RAGDOLL_MAXPARTS]; // Stores whether the part is static or dynamic
bool parts_nophys[RAGDOLL_MAXPARTS]; // Stores whether the part has no physics
vector parts_pos[RAGDOLL_MAXPARTS]; // Stores the position of the parts
vector parts_ang[RAGDOLL_MAXPARTS]; // Stores the angles of the parts
string parts_conPtcSnd[RAGDOLL_MAXPARTS]; // Particle and sound effect to spawn when the part hits the ground
vector parts_wmat0[RAGDOLL_MAXPARTS]; // Matrix[0] of the part in the world
vector parts_wmat1[RAGDOLL_MAXPARTS]; // Matrix[1] of the part in the world
vector parts_wmat2[RAGDOLL_MAXPARTS]; // Matrix[2] of the part in the world
vector parts_wmat3[RAGDOLL_MAXPARTS]; // Matrix[3] of the part in the world
vector parts_velLin[RAGDOLL_MAXPARTS]; // Linear velocity of the part in the world
vector parts_velAng[RAGDOLL_MAXPARTS]; // Angular velocity of the part in the world
int parts_num; // Stores the amount of parts
void SetOwnerPtr(Location location);
void FillData_GenVars(float genFloats[], int genInts[], vector genVecs[], string genStrings[]);
void FillData_Parts1(float mass[], string models[], string names[], bool statics[], bool nophys[], vector poss[], vector angs[], string ptc[]);
void FillData_Parts2(vector mat0[], vector mat1[], vector mat2[], vector mat3[], vector vellin[], vector velang[]);
void FillData_Blocks(int part1[], int part2[]);
void FillData_Joints(vector angles[], vector limitlo[], vector limithi[], float springstiff[], float springdamp[], int part1[], int part2[]);
void ClearData();
void RagdollObject();
void ~RagdollObject();
}
//=================================================================
// store object base
//=================================================================
class StoreObject_Base extends GameObject
{
int worldID;
vector worldMatrix[4];
bool isNetworkObject;
}
//=================================================================
// static object storage
//=================================================================
class StaticObject extends StoreObject_Base
{
string modelPath;
string remapPath;
}
//=================================================================
// dynamic object storage
//=================================================================
class DynamicObject extends StoreObject_Base
{
string modelPath;
string remapPath;
string fxPath;
vector worldAngVelocity;
vector worldVelocity;
float modelMass;
}
//=================================================================
// projectile object storage
//=================================================================
class ProjectileObject extends StoreObject_Base
{
string modelPath;
string fxPath;
string ptcPath;
vector worldAngVelocity;
vector worldVelocity;
float modelMass;
float deathTime;
bool deathOnImpact;
}
//=================================================================
// particle object storage
//=================================================================
class ParticleObject extends StoreObject_Base
{
string ptcPath;
float ptcTime;
int priority;
}
//=================================================================
// event fx object storage
//=================================================================
class EventFXObject extends StoreObject_Base
{
string sndPath;
string ptcPath;
}
//=================================================================
// event script object storage
//=================================================================
class EventScriptObject extends StoreObject_Base
{
string scriptPath;
}
//=================================================================
// event timer object storage
//=================================================================
class EventTimerObject extends StoreObject_Base
{
float CounterCurrent;
float CounterTarget;
int CounterRepeatsCurrent;
int CounterRepeatsTotal;
bool CounterRunning;
string LinkEntIDs;
}
//=================================================================
// trigger object storage
//=================================================================
class TriggerObject extends StoreObject_Base
{
float radius;
float height;
bool trigOnExitType;
bool trigOnStartType;
bool trigVehicle;
bool trigProjectile;
bool trigDynamic;
bool trigOnce;
bool triggered;
int linkIDs[TRIGGER_MAXLINKS];
}
//=================================================================
// waterzone object storage
//=================================================================
class WaterZoneObject extends StoreObject_Base
{
float width;
float length;
float depth;
float density;
vector watercolor;
float murkiness;
float caustic;
float watercurrent;
bool disableEffects;
}
//=================================================================
// building block storage
//=================================================================
class BuildingBlockObject extends StoreObject_Base
{
Inventory inventory;
string configFile;
string modelPath;
string remapPath;
string customScript;
string activateText;
string activateImage;
string fxPath;
vector worldAngVelocity;
vector worldVelocity;
float modelMass;
int genInt;
float genFloat;
vector genVec;
string genString;
void SetGenString(string genStr)
{
genString = genStr;
}
float buildPctTime;
float buildTime;
bool isInTransition;
bool isActivated;
bool isDynamic;
vector custom_GridSnap;
vector powerpoint_pos[POWERPOINTS_MAX];
vector powerpoint_ang[POWERPOINTS_MAX];
bool powerpoint_out[POWERPOINTS_MAX];
int powerpoint_connect_ID[POWERPOINTS_MAX];
int powerpoint_connect_SubID[POWERPOINTS_MAX];
int powerpoint_connect_Slot[POWERPOINTS_MAX];
int powerpoint_num;
vector seats_Pos[BUILDBLOCK_MAXCHARACTERSEATS];
vector seats_Ang[BUILDBLOCK_MAXCHARACTERSEATS];
vector seats_ExitPos[BUILDBLOCK_MAXCHARACTERSEATS];
vector seats_ExitAng[BUILDBLOCK_MAXCHARACTERSEATS];
bool seats_CanSleep[BUILDBLOCK_MAXCHARACTERSEATS];
string seats_InAnim[BUILDBLOCK_MAXCHARACTERSEATS];
string seats_OutAnim[BUILDBLOCK_MAXCHARACTERSEATS];
string seats_Anim[BUILDBLOCK_MAXCHARACTERSEATS];
int seats_CharacterID[BUILDBLOCK_MAXCHARACTERSEATS];
int seats_Num;
string slots_Types[BUILDBLOCK_SLOTSMAX];
int slots_LinkEntID[BUILDBLOCK_SLOTSMAX];
vector slots_Pos[BUILDBLOCK_SLOTSMAX];
vector slots_Ang[BUILDBLOCK_SLOTSMAX];
bool slots_SingleDir[BUILDBLOCK_SLOTSMAX];
bool slots_NoWorldSnap[BUILDBLOCK_SLOTSMAX];
bool slots_PreventDisassemble[BUILDBLOCK_SLOTSMAX];
bool slots_SealsAtmosphere[BUILDBLOCK_SLOTSMAX];
int slotsNum;
string resStore_ResName[BUILDBLOCK_RESSTOREMAX];
int resStore_Amount[BUILDBLOCK_RESSTOREMAX];
int resStore_MaxAmount[BUILDBLOCK_RESSTOREMAX];
int resStoreNum;
string resCost_ResName[BUILDBLOCK_RESCOSTMAX];
int resCost_Amount[BUILDBLOCK_RESCOSTMAX];
int resCostNum;
vector atmoNorms_Pos[BUILDBLOCK_ATMONORMALSMAX];
vector atmoNorms_Dir[BUILDBLOCK_ATMONORMALSMAX];
int atmoNormsNum;
vector atmoWholeZones_Mins[BUILDBLOCK_ATMOZONESMAX];
vector atmoWholeZones_Maxs[BUILDBLOCK_ATMOZONESMAX];
int atmoWholeZonesNum;
vector move_Start_Mat[4];
vector move_End_Pos;
vector move_End_Ang;
float move_PctTime;
float move_Time;
float move_DelayTime;
bool move_OnTouch;
bool move_OnActivate;
int move_State;
bool move_Stopped;
float anim_Rate;
float anim_Time;
float anim_State;
vector demountMat[4];
bool demountGround;
vector transitionMat_Start[4];
vector transitionMat_End[4];
float transitionMat_Time;
bool transitionMat_ToGround;
bool transitionMat_NoWorldSnap;
bool transitionMat_Demount;
void ~BuildingBlockObject();
}
//=================================================================
// building block group storage
//=================================================================
class BuildingBlockGroupObject extends GameObject
{
int groupIndex;
vector displayColor;
int blockIDs[GROUP_BUILDBLOCK_MAXBLOCKS];
int blockIDs_num;
void ClearBlockIDs()
{
for (int i = 0; i < GROUP_BUILDBLOCK_MAXBLOCKS; i++)
{
blockIDs[i] = 0;
}
blockIDs_num = 0;
}
void BuildingBlockGroupObject()
{
ClearBlockIDs();
}
}
//=================================================================
// inventory class
//=================================================================
class Inventory extends GameObject
{
class classParent;
int indexInParent;
int parentEntID;
InventoryItemObject slotItem[INVENTORY_SLOTS_MAX]; // Item in each slot
string slotType[INVENTORY_SLOTS_MAX]; // Slot type, undefined type means universal slot type
bool slotHighlight[INVENTORY_SLOTS_MAX]; // Can be used to highlight the slot
int slotNum;
string layoutPath;
string highlightText;
string highlightImage;
string customTitle; // Can be set to display custom title above inventory
void SetCustomTitle(string tit)
{
customTitle = tit;
}
int GetTotalItemCount()
{
int result = 0;
for (int slt = 0; slt < slotNum; slt++)
{
if (slotItem[slt])
result++;
}
return result;
}
void SetSlotHighlight(int index, bool enable)
{
slotHighlight[index] = enable;
}
void SetSlotType(int index, string type);
void ClearInventory(bool deleteSlots);
void DeleteInventoryItems(bool deleteSlots);
void CreateInventoryItemsIDs();
bool CanPutItemIntoSlot(InventoryItemObject item, int index, bool ignoreSlotTypes);
bool GetSlotFree(int index);
int GetSlotByItem(InventoryItemObject item);
int GetFreeSlotForItem(InventoryItemObject item, bool ignoreSlotTypes, bool fromEnd);
InventoryItemObject GetItemInSlot(int index);
bool AddItem(InventoryItemObject item, int index);
bool RemoveItem(InventoryItemObject item);
void LoadItemScripts();
void DeleteItemScripts();
void RestoreItemIDs();
string GetStringForVar(string varName, int optional_OnlySlot);
int GetIntForVar(string varName, int optional_OnlySlot);
float GetFloatForVar(string varName, int optional_OnlySlot);
bool GetBoolForVar(string varName, int optional_OnlySlot);
vector GetVectorForVar(string varName, int optional_OnlySlot);
void OnInventoryChanged()
{
if (parentEntID <= 0)
return;
_entity parentEnt = FindEntityByID(g_Game.CurrentWorld, parentEntID);
if (!parentEnt)
return;
if (!IsInherited(parentEnt, Type("TKOM_Entity")))
return;
TKOM_Entity parentTKOMEnt = (TKOM_Entity)parentEnt;
parentTKOMEnt.OnInventoryChanged();
}
void OnInventoryAccessing(widget rootWidget, float timeSlice)
{
if (parentEntID <= 0)
return;
_entity parentEnt = FindEntityByID(g_Game.CurrentWorld, parentEntID);
if (!parentEnt)
return;
if (!IsInherited(parentEnt, Type("TKOM_Entity")))
return;
TKOM_Entity parentTKOMEnt = (TKOM_Entity)parentEnt;
parentTKOMEnt.OnInventoryAccessing(rootWidget, timeSlice);
}
void ItemsOnEvent(string eventName);
void ItemsOnEventWithForce(string eventName, vector pos, vector force);
void ItemsOnEventWithInt(string eventName, int input);
void ItemsOnEventWithFloat(string eventName, float input);
void ItemsOnEventWithVector(string eventName, vector input);
void ItemsOnEventWithString(string eventName, string input);
void ItemsOnEventWithEntity(string eventName, _entity ent);
void ItemsOnFrame();
void ItemsOnPostFrame();
void ItemsOnSimulate();
InventoryItemObject SpawnStoredItemObject(int itemID, int ownerSlot, string title, string desc, string image, string script, string config, string mdlPath, string rmpPath, string fxPath, float mass, string validSlotsStr, int genInt, float genFloat, vector genVec, string genStr);
void SetParent(class parent, int id, int index)
{
classParent = parent;
indexInParent = index;
parentEntID = id;
}
void Inventory(string invName, class parent, int index, int id, string layout, string hiText, string hiImg, int numSlots, string slotTypes[])
{
ClearInventory(true);
name = invName;
slotNum = numSlots;
layoutPath = layout;
classParent = parent;
indexInParent = index;
parentEntID = id;
highlightText = hiText;
highlightImage = hiImg;
for (int slt = 0; slt < numSlots; slt++)
{
SetSlotType(slt, slotTypes[slt]);
}
}
void ~Inventory()
{
DeleteInventoryItems(true);
}
}
//=================================================================
// inventory item controller
//=================================================================
class InventoryItemController extends Controller
{
void IIController_Init(InventoryItemObject owner)
{
}
void IIController_Exit(InventoryItemObject owner)
{
}
void IIController_OnRemoveFromInventory(InventoryItemObject owner, Inventory inventory, int slot)
{
}
void IIController_OnMoveToInventory(InventoryItemObject owner, Inventory inventory, int slot)
{
}
void IIController_OnMoveWithinInventory(InventoryItemObject owner, Inventory inventory, int newSlot, int oldSlot)
{
}
void IIController_OnMoveItemToWorld(InventoryItemObject owner, TKOM_Entity itemEnt)
{
}
bool IIController_GetCanRemoveFromInventory(InventoryItemObject owner, Inventory inventory, int slot)
{
return true;
}
bool IIController_GetCanMoveToInventory(InventoryItemObject owner, Inventory inventory, int slot)
{
return true;
}
bool IIController_GetCanMoveWithinInventory(InventoryItemObject owner, Inventory inventory, int newSlot, int oldSlot)
{
return true;
}
bool IIController_GetCanMoveItemToWorld(InventoryItemObject owner)
{
return true;
}
string IIController_GetStringForVar(string varName)
{
return "";
}
int IIController_GetIntForVar(string varName)
{
return 0;
}
float IIController_GetFloatForVar(string varName)
{
return 0;
}
bool IIController_GetBoolForVar(string varName)
{
return false;
}
vector IIController_GetVectorForVar(string varName)
{
return ZeroVec;
}
void IIController_OnEvent(string eventName)
{
}
void IIController_OnEventWithForce(string eventName, vector pos, vector force)
{
}
void IIController_OnEventWithInt(string eventName, int value)
{
}
void IIController_OnEventWithFloat(string eventName, float value)
{
}
void IIController_OnEventWithVector(string eventName, vector value)
{
}
void IIController_OnEventWithString(string eventName, string value)
{
}
void IIController_OnEventWithEntity(string eventName, _entity ent)
{
}
int IIController_FillInventoryOptions(string options[], CharacterObject caller)
{
return 0;
}
void IIController_OnInventoryOption(int option, CharacterObject caller)
{
}
void IIController_OnInventoryEvent(string eventName, CharacterObject caller)
{
}
void IIController_OnFrm()
{
}
void IIController_OnPFrm()
{
}
void IIController_OnSim()
{
}
void IIController_OnItemInWater(WaterZone water, int extra)
{
}
}
//=================================================================
// inventory item storage
//=================================================================
class InventoryItemObject extends StoreObject_Base
{
Inventory inventoryParent;
int inventorySlot;
ScriptModule smodule;
InventoryItemController controller;
string itemTitle;
string itemDesc;
string itemImage;
string itemScript;
string configFile;
string modelPath;
string remapPath;
string fxPath;
float modelMass;
string delayReplaceCFG; // Config of inventory item to use for delayed replacing of item
bool Highlight; // Can be used to highlight the item in an inventory etc
bool delayDelete;
void DeleteItem()
{
delayDelete = true;
}
bool GetShouldDelete()
{
return delayDelete;
}
void ReplaceItemWithCFG(string cfg)
{
delayReplaceCFG = cfg;
DeleteItem();
}
void SetHighlight(bool enable)
{
Highlight = enable;
}
// Generic variables
int GenInt;
float GenFloat;
vector GenVec;
string GenString;
void SetGenString(string genStr)
{
GenString = genStr;
}
// Multiplayer variable synching
int mpGenInt;
float mpGenFloat;
vector mpGenVec;
string mpGenString;
void SynchGenInt();
void SynchGenFloat();
void SynchGenVec();
void SynchGenString();
bool GetAnyGenVarsSet()
{
if (GenInt != 0)
return true;
if (GenFloat != 0)
return true;
if (GenVec != ZeroVec)
return true;
if (GenString != "")
return true;
return false;
}
vector worldAngVelocity;
vector worldVelocity;
string validSlotTypes[INVENTORY_VALIDSLOTS_MAX];
int validSlotTypesNum;
void DeleteCustomScript();
void LoadCustomScript(string scriptToLoad);
bool CanPutIntoSlotType(string type);
void ClearValidSlotTypes();
void AddValidSlotType(string type);
void SetValidSlotTypes(string types[], int num);
void ParseValidSlotTypesFromString(string slotTypesStr);
string WriteValidSlotTypesToString();
void RemoveFromInventory();
bool MoveToInventory(Inventory inv, int slot, bool ignoreSlotTypes);
bool MoveWithinInventory(Inventory inv, int newSlot, bool ignoreSlotTypes);
TKOM_Entity MoveItemToWorld(vector mat[4], vector velLin, vector velAng);
TKOM_Entity MoveItemToWorldClient(int wldItmID);
bool GetCanRemoveFromInventory(Inventory inv, int slot);
bool GetCanMoveToInventory(Inventory inv, int slot);
bool GetCanMoveWithinInventory(Inventory inv, int newSlot, int oldSlot);
bool GetCanMoveToWorld();
void OnItemEvent(string eventName);
void OnItemEventWithForce(string eventName, vector pos, vector force);
void OnItemEventWithInt(string eventName, int input);
void OnItemEventWithFloat(string eventName, float input);
void OnItemEventWithVector(string eventName, vector input);
void OnItemEventWithString(string eventName, string input);
void OnItemEventWithEntity(string eventName, _entity ent);
void OnItemFrame();
void OnItemPostFrame();
void OnItemSimulate();
void OnItemInWater(WaterZone water, int extra);
int FillInventoryOptions(string options[], CharacterObject caller);
void OnInventoryOption(int option, CharacterObject caller);
void OnInventoryEvent(string eventName, CharacterObject caller);
int mpID;
void CreateID();
void SetItemID(int id);
int GetItemID();
void RestoreInvItemID()
{
if (!Global_GetInventoryItemByID(mpID))
Global_AddInvItem(this);
if (Global_HighestInvItemID < mpID)
Global_HighestInvItemID = mpID;
}
void InventoryItemObject()
{
inventoryParent = NULL;
inventorySlot = -1;
worldID = -1;
itemTitle = "UNTITLED";
itemDesc = "NO DESCRIPTION";
itemImage = "";
itemScript = "";
configFile = "";
DeleteCustomScript();
ClearValidSlotTypes();
Highlight = false;
GenInt = 0;
GenFloat = 0;
GenVec = ZeroVec;
GenString = "";
mpID = -1;
Global_AddInvItem(this);
delayDelete = false;
delayReplaceCFG = "";
}
void ~InventoryItemObject()
{
RemoveFromInventory();
DeleteCustomScript();
Global_RemoveInvItem(this);
}
}
void MPSafe_DeleteInventoryItemObject(InventoryItemObject item);
Inventory GetInventoryByIDAndIndex(int id, int index);
void MoveToOtherInventory(int id, int invIndex, int invItemIndex, int newID, int newInvIndex, int newSlot, bool ignoreSlotTypes);
void MoveWithinInventory(int id, int invIndex, int invItemIndex, int newSlot, bool ignoreSlotTypes);
int MoveToWorld(int id, int invIndex, int invItemIndex, int worldItemID, int grabUnitID, vector invItemMat[4]);
int MoveToInventory(int id, int invIndex, int slot, int itmID, bool ignoreSlotTypes);
const int MAX_OBJECTS_PER_LOCATION = 16384;
const int RESOURCE_MAXTYPES = 128;
const int RESOURCE_SECTOR_SIZE = 1600; // 50m, default, can be overridden in .loc file for location
const int RESOURCE_SECTOR_MAXNUM = 160; // 8km^2 if RESOURCE_SECTOR_SIZE is 50m (RESOURCE_SECTOR_MAXNUM * RESOURCE_SECTOR_SIZE = size in units)
const int RESOURCE_AREATYPE_GROUND = 0;
const int RESOURCE_AREATYPE_SURFACE = 1;
const int RESOURCE_AREATYPE_ATMOSPHERIC = 2;
//=================================================================
// resource base
//=================================================================
class Resource_Base extends GameObject
{
Location owner;
int index;
// 'name' is the resource type name
string title;
string desc;
vector displayColor;
int areaType;
int Amount[RESOURCE_SECTOR_MAXNUM][RESOURCE_SECTOR_MAXNUM];
bool Changed[RESOURCE_SECTOR_MAXNUM][RESOURCE_SECTOR_MAXNUM]; // If true, will store changes in scenario files etc
// Store the distribution input values
int distrib_MaxAmountTotal;
int distrib_AmountAverage;
float distrib_Clumping;
int distrib_SectorNumX;
int distrib_SectorNumY;
int distributeSeed;
// Returns whether the resource has been 'discovered' in the input sector
bool IsDiscoveredInSector(int sectorX, int sectorY);
// Returns total amount of resource left
int GetTotalAmount()
{
int result = 0;
for (int x = 0; x < distrib_SectorNumX; x++)
{
for (int y = 0; y < distrib_SectorNumY; y++)
{
result += Amount[x][y];
}
}
return result;
}
// Returns how 'rich' a sector is compared to the average of distrib_MaxAmountTotal
float GetSectorRichness(int sectorX, int sectorY)
{
float amt = Amount[sectorX][sectorY];
if (distrib_AmountAverage > 0)
amt = amt / distrib_AmountAverage;
return amt;
}
// Returns maximum amount of resource extracted, relative to input extraction value (more or less unused)
int GetMaxAmountPerExtraction(int extractAmountMax)
{
if (distrib_SectorNumX == 0 || distrib_SectorNumY == 0)
return 0;
if (distrib_MaxAmountTotal == 0)
return 0;
if (extractAmountMax == 0)
return 0;
int amt = floor(distrib_MaxAmountTotal / fsum(distrib_SectorNumX * distrib_SectorNumY));
amt /= extractAmountMax;
if (amt <= 0)
amt = 1;
return amt;
}
// Returns extraction scaler based on amount in sector relative to input 'efficient' amount
float GetExtractScale(int efficientAmount, int sectorX, int sectorY, float minScale, float maxScale)
{
float scale = Amount[sectorX][sectorY] / efficientAmount;
clamp scale;
return scale;
}
void RandomizeSeed()
{
distributeSeed = rand(1, 2000000000);
}
void SetAmountInSector(int amount, int sectorX, int sectorY)
{
int amtInSector_previous = Amount[sectorX][sectorY];
int amtInSector = amount + 100000;
Amount[sectorX][sectorY] = amtInSector;
if (amtInSector != amtInSector_previous)
Changed[sectorX][sectorY] = true;
}
void AddAmountToSector(int amount, int sectorX, int sectorY)
{
if (amount < 0)
return;
int amtInSector_previous = Amount[sectorX][sectorY];
int amtInSector = amtInSector_previous + amount;
Amount[sectorX][sectorY] = amtInSector;
if (amtInSector != amtInSector_previous)
Changed[sectorX][sectorY] = true;
}
int TakeAmountFromSector(int amount, int sectorX, int sectorY, bool clampToMin)
{
int amtInSector_previous = Amount[sectorX][sectorY];
int amtInSector = amtInSector_previous;
clamp amount<0, amtInSector>;
amtInSector -= amount;
if (clampToMin && amtInSector <= 0 && amtInSector_previous > 0)
amtInSector = 1;
Amount[sectorX][sectorY] = amtInSector;
if (amtInSector != amtInSector_previous)
Changed[sectorX][sectorY] = true;
return amount;
}
void MPSynchSector(int sectorX, int sectorY);
int GetSectorAmount(int sectorX, int sectorY)
{
int amount = Amount[sectorX][sectorY];
return amount;
}
void SetDistributionParams(int maxAmountTotal, float distribClumping, int sectorNumX, int sectorNumY)
{
distrib_MaxAmountTotal = maxAmountTotal;
distrib_Clumping = distribClumping;
distrib_SectorNumX = sectorNumX;
distrib_SectorNumY = sectorNumY;
clamp distrib_Clumping<0, 1>;
distrib_AmountAverage = distrib_SectorNumX * distrib_SectorNumY;
if (distrib_AmountAverage > 0)
distrib_AmountAverage = distrib_MaxAmountTotal / distrib_AmountAverage;
}
void ClearResource()
{
for (int x = 0; x < RESOURCE_SECTOR_MAXNUM; x++)
{
for (int y = 0; y < RESOURCE_SECTOR_MAXNUM; y++)
{
Amount[x][y] = 0;
Changed[x][y] = false;
}
}
}
void DistributeResource();
void DebugDisplayInWorld();
void DebugHighlightSectorInWorld(int x, int y);
void Resource_Base(Location caller, string strName, string strTitle, string strDesc, vector vecColor, int intAreaType)
{
index = -1;
owner = caller;
displayColor = vecColor;
name = strName;
title = strTitle;
desc = strDesc;
areaType = intAreaType;
ClearResource();
RandomizeSeed();
}
}
const int LOCATION_MP_MAXCUSTOM = 8;
//=================================================================
// location object. (Victoria crater etc...)
//=================================================================
class Location extends GameObject
{
int StoredScnFileVersion; // For compatibility
float MP_CustomFloat[LOCATION_MP_MAXCUSTOM];
bool MP_CustomFloatUsed[LOCATION_MP_MAXCUSTOM];
void ClearMPCustom()
{
for (int l = 0; l < LOCATION_MP_MAXCUSTOM; l++)
{
MP_CustomFloat[l] = 0;
MP_CustomFloatUsed[l] = false;
}
}
void SetMPCustomFloat(int index, float value)
{
MP_CustomFloatUsed[index] = true;
MP_CustomFloat[index] = value;
}
float GetMPCustomFloat(int index)
{
float result = MP_CustomFloat[index];
return result;
}
void OnNetUpdate_Custom(PacketOutputAdapter output)
{
int numToSynch = 0;
for (int l = 0; l < LOCATION_MP_MAXCUSTOM; l++)
{
if (MP_CustomFloatUsed[l])
numToSynch++;
}
output.WriteIntAsUByte(numToSynch);
for (l = 0; l < LOCATION_MP_MAXCUSTOM; l++)
{
if (!MP_CustomFloatUsed[l])
continue;
float val = MP_CustomFloat[l];
output.WriteIntAsUByte(l);
output.WriteFloat(val);
}
}
void OnNetMessage_Custom(PacketInputAdapter input)
{
int numToSynch = input.ReadIntAsUByte();
for (int l = 0; l < numToSynch; l++)
{
int index = input.ReadIntAsUByte();
float value = input.ReadFloat();
SetMPCustomFloat(index, value);
}
}
// Storage of scenario objects, such as static rocks, dynamic rocks, projectiles, etc during saving (after load creates objects and clear the list)
StoreObject_Base objects[MAX_OBJECTS_PER_LOCATION];
int objectsCount;
StoreObject_Base CreateStoreObject(string objType);
void AddCreatedStoreObject(StoreObject_Base storeObj);
void StoreObject(TKOM_Entity tkomEnt); // Stores the object in the location (only for certain types)
void RestoreObjects();
void ClearStoreObjects();
void OnAfterLoad();
// Storage of building block groups
BuildingBlockGroupObject bblockGroups[GROUP_BUILDBLOCK_MAXGROUPS];
int bblockGroupsCount;
void StoreBBlockGroups();
void RestoreBBlockGroups();
void ClearStoredBBlockGroups();
void RegenerateCompatibilityBBlockGroups(); // Regenerates proper groups for building blocks (ensures compatibility)
float longitude;
float latitude;
float bodyCenterDist;
bool locked;
bool hidden;
int unlockCost;
string loc_loadScnObjPath; // Path to the campaign scenario file (for objects loading)
string loc_title;
string loc_desc;
string loc_body;
string loc_parentbody;
string loc_path; // Path to the location's .ent file
string loc_prev_image;
string loc_map_image;
vector loc_gravity;
vector loc_worldbounds;
vector loc_worldsize;
vector loc_reentryVel; // The velocity that vehicles approach the location at
vector loc_reentryOffsetPos; // The offset position from the target position that vehicles approach the location at
vector loc_reentryOffsetAng; // The offset angles that vehicles approach the location at
float loc_airfriction;
string loc_skypreset;
vector loc_editorUTC_DMY;
vector loc_editorUTC_HMS;
float loc_sectorSize; // Size of sectors in location (for resources)
float loc_weatherVal; // Current value of weather on the location
float loc_weatherFXDelay; // Stores the delay between spawning weather effects (such as meteors)
float loc_weatherForecast[MAX_WEATHERFORECAST_HOURS]; // Stores the upcoming weather forecast values for the next MAX_WEATHERFORECAST_HOURS number of hours
float loc_weatherForecast_currentHour; // Stores the current hour (from 0 to 1, then restarts)
float WeatherGetHourForecast(); // Returns the forecasted weather for an hour ahead
float WeatherGetForecastBias(int numHours); // Returns the overall bias of the forecast weather for the input number of hours ahead
void WeatherGenerateForecast(int numHours, bool completeRefresh, bool editorMode, float weatherBias); // Generates a weather forecast for the next numHours number of hours
void WeatherUpdate(float fTimeSlice);
void WeatherSkip(int numHours);
bool WeatherIsNull();
void UpdateBadWeatherNotifications();
VehicleObject vehicles[MAX_VEHICLES_PER_LOCATION];
int vehiclesCount;
RagdollObject ragdolls[MAX_RAGDOLLS_PER_LOCATION];
int ragdollsCount;
ScienceTarget scienceTargets[MAX_SCIENCE_TARGETS_PER_LOCATION];
int scienceTargetsCount;
ScienceTarget lastSelectedMission;
void Location();
void ~Location();
VehicleObject FindVehicle(string name);
VehicleObject FindVehicleByCFG(string cfgPath);
VehicleObject FindVehicleByCFGAndTeam(string cfgPath, int team);
VehicleObject FindVehicleByStoreID(int storeID);
VehicleObject CreateVehicle(string name);
VehicleObject CreateNamedVehicle();
CharacterObject CreateCharacter(string name);
CharacterObject CreateNamedCharacter();
RagdollObject FindRagdollByStoreID(int storeID);
RagdollObject CreateRagdoll();
void DestroyVehicle(VehicleObject vehicle);
void DestroyVehicleByIndex(int index);
void DestroyVehicles();
int FindVehicleIndex(VehicleObject vehicle);
void DestroyVehicleInstance(VehicleObject vehicle);
void DestroyRagdoll(RagdollObject ragdollStore);
void DestroyRagdollByIndex(int index);
void DestroyRagdolls();
int FindRagdollIndex(RagdollObject ragdollStore);
void DestroyRagdollInstance(RagdollObject ragdollStore);
bool IsLocked();
void Unlock();
bool IsHidden();
void Hide(bool hide);
void DoAnalysis(TKOM_Entity vehicle, string instSubType, int physMat, string specMat, vector pos);
void DoPhoto(TKOM_Entity vehicle, int camNum, vector camPos, bool color);
ScienceTarget FindScienceTarget(string name, bool recursive);
ScienceTarget FindScienceTargetDuplicate(string name, bool recursive, int dupNum);
ScienceTarget CreateGenericScienceTarget(ScienceTarget parent, string name, Location loc);
ScienceTargetPhoto CreatePhotoScienceTarget(ScienceTarget parent, string name, Location loc);
ScienceTargetAnalyze CreateAnalyzeScienceTarget(ScienceTarget parent, string name, Location loc);
ScienceTarget CreateScienceTargetByTypeID(string typeID, ScienceTarget parent, string name, Location loc);
STargetZone CreateScienceTargetZone(ScienceTarget owner);
ScienceTarget GetFirstEnabledMission();
void ReCallSTOnComp();
void AddScienceTarget(ScienceTarget target);
bool RemoveScienceTarget(ScienceTarget target);
void RemoveOnCompST(string onCompST);
void UpdateWorldSTZones();
void UpdateSTVisualizers(bool show_sts, bool show_lnk);
void DestroyScienceTargets();
void ReadSCNSTs(tparse file, bool checkForPrev);
bool GetScienceTargetsFromSCN(string fileName, bool checkForPrevious);
void WriteScienceTargetsToSCN(int file, local int level);
void SetWorldParameters();
void SetEditorUTC();
bool Load(string fileName, bool reloading);
int ConvertPriority(string str);
void PrintData();
void SetLastSelectedMission(ScienceTarget mission);
int GetEnabledMissionsCount();
string GetEntFilePath();
string GetLocFilePath();
bool IsSpaceLocation()
{
if (VectorLength(loc_gravity) < GRAVITY_ZERO)
return true;
else
return false;
}
bool IsGroundLocation()
{
if (VectorLength(loc_gravity) < GRAVITY_ZERO)
return false;
else
return true;
}
bool IsLowGravityLocation()
{
if (VectorLength(loc_gravity) < GRAVITY_LOW)
return true;
else
return false;
}
// Satellite related
bool SatelliteTrackVehicle;
float SatelliteZoomLevel;
vector SatellitePos;
// Resources for the manned mission section
bool ResourceDiscovered_Ground[RESOURCE_SECTOR_MAXNUM][RESOURCE_SECTOR_MAXNUM];
bool ResourceDiscovered_Surface[RESOURCE_SECTOR_MAXNUM][RESOURCE_SECTOR_MAXNUM];
bool ResourceDiscovered_Atmospheric[RESOURCE_SECTOR_MAXNUM][RESOURCE_SECTOR_MAXNUM];
Resource_Base Resources[RESOURCE_MAXTYPES];
int ResourcesNum;
int ResourcesSectorNum_X;
int ResourcesSectorNum_Y;
void AddDefaultResources();
void CalculateResourceSectorNums();
void DestroyResources()
{
for (int i = 0; i < ResourcesNum; i++)
{
Resource_Base rscEnt = Resources[i];
if (rscEnt)
delete rscEnt;
Resources[i] = NULL;
}
ResourcesNum = 0;
}
Resource_Base FindResourceByName(string resourceName)
{
for (int r = 0; r < ResourcesNum; r++)
{
Resource_Base rscEnt = Resources[r];
if (rscEnt && rscEnt.name == resourceName)
return rscEnt;
}
return NULL;
}
// Sets the resource type at the sector and surrounding sectors as discovered
void DiscoverResourceAtSector(int resType, int sectorX, int sectorY, float sectorRadius, bool notify);
void ClearDiscoveredSectors()
{
for (int x = 0; x < RESOURCE_SECTOR_MAXNUM; x++)
{
for (int y = 0; y < RESOURCE_SECTOR_MAXNUM; y++)
{
ResourceDiscovered_Ground[x][y] = false;
ResourceDiscovered_Surface[x][y] = false;
ResourceDiscovered_Atmospheric[x][y] = false;
}
}
}
void RandomizeResourceSeeds()
{
for (int r = 0; r < ResourcesNum; r++)
{
Resource_Base rscEnt = Resources[r];
if (rscEnt)
rscEnt.RandomizeSeed();
}
}
// Adds a new resource type with input name, maximum amount of resource per sector, and how much the resource distribution should form clumps
Resource_Base AddResourceType(string resourceName, string resourceTitle, string resourceDesc, int maxAmountTotal, float distribClumping, vector vecColor, int intAreaType)
{
Resource_Base rscBase = new Resource_Base(this, resourceName, resourceTitle, resourceDesc, vecColor, intAreaType);
rscBase.SetDistributionParams(maxAmountTotal, distribClumping, ResourcesSectorNum_X, ResourcesSectorNum_Y);
rscBase.index = ResourcesNum;
Resources[ResourcesNum] = rscBase;
ResourcesNum++;
return rscBase;
}
// Sets the amount of a resource in a particular sector
void SetResourceAmountInSector(string resourceName, int amount, int sectorX, int sectorY)
{
Resource_Base rscEnt = FindResourceByName(resourceName);
if (!rscEnt)
return;
rscEnt.SetAmountInSector(amount, sectorX, sectorY);
}
// Tells each resource to distribute itself across the location
void DistributeResources()
{
for (int r = 0; r < ResourcesNum; r++)
{
Resource_Base rscEnt = Resources[r];
if (rscEnt)
rscEnt.DistributeResource();
}
}
// Returns the X coordinate for the sector the input position X is in
int GetSectorAtPosX(float posX)
{
int result = floor(posX + fsum(loc_worldsize[0] * 0.5) - fsum(loc_sectorSize * 0.5) / loc_sectorSize);
int maxX = ResourcesSectorNum_X - 1;
clamp result<0, maxX>;
return result;
}
// Returns the Y coordinate for the sector the input position Y is in
int GetSectorAtPosY(float posY)
{
int result = floor(posY + fsum(loc_worldsize[1] * 0.5) - fsum(loc_sectorSize * 0.5) / loc_sectorSize);
int maxY = ResourcesSectorNum_Y - 1;
clamp result<0, maxY>;
return result;
}
//! MULTIPLAYER: See comment in GameEntity class
void OnNetObjectInitSend( PacketOutputAdapter output );
void OnNetObjectInitReceived( PacketInputAdapter input );
void OnNetObjectAfterInitSend( PacketOutputAdapter output );
void OnNetObjectAfterInitReceived( PacketInputAdapter input );
void OnNetUpdate( PacketOutputAdapter output );
bool OnNetMessage( PacketInputAdapter input );
bool OnRPC(int proc, PacketInputAdapter input);
void RP_UpdateResource(int resIndex, int sectorX, int sectorY, int amount, bool isRemoteCall);
}
const int MAX_PLANETS = 32;
const int MAX_LOCATIONS_PER_PLANET = 64;
//=================================================================
// planet object. (contains locations)
//=================================================================
class Planet extends class//GameObject
{
string name;
string title;
string description;
int index;
string model;
string highlightRemap;
float cameraDist;
Location locations[MAX_LOCATIONS_PER_PLANET];
int locationsCount;
void RegisterLocation(Location loc);
bool Load(string fileName);
void Planet();
}
//-----------------------------------------------------------------------------
//! Net player class
class NetPlayerTKOM extends NetPlayer
{
Vehicle_Handler currentVehicle;
bool typing;
void NetPlayerTKOM();
void ~NetPlayerTKOM();
void SetVehicle(Vehicle_Handler vehicle);
bool SelectVehicleOnLocal(int vehicle);
bool IsCallToLocal(bool isRemoteCall);
bool IsCallToServer(bool isRemoteCall);
bool IsCallToClients(bool isRemoteCall);
void OnUpdate(float timeslice); //every frame
bool IsTyping();
void RP_SelectVehicle(int vehicle, bool isRemoteCall = false);
void RP_AddChatMessage(string message, bool isRemoteCall = false);
void RP_SendPopup(bool noAlphaChange, bool clearPrevious, float time, string layout, string titStr, string descStr, string descStr2, bool isRemoteCall = false);
void RP_DoPopupForPlayer(int playerIndex, bool noAlphaChange, bool clearPrevious, float time, string layout, string titStr, string descStr, string descStr2, bool isRemoteCall = false);
void RP_DeleteInventoryItem(int itemID, int wldItemID, bool isRemoteCall = false);
void RP_UpdateInventoryItem_GenInt(int itemID, int genInt, bool isRemoteCall = false);
void RP_UpdateInventoryItem_GenFloat(int itemID, float genFloat, bool isRemoteCall = false);
void RP_UpdateInventoryItem_GenVec(int itemID, vector genVec, bool isRemoteCall = false);
void RP_UpdateInventoryItem_GenString(int itemID, string genString, bool isRemoteCall = false);
void RP_InventoryItemOption(int itemID, int callerID, int option, bool isRemoteCall = false);
void RP_InventoryItemEvent(int itemID, int callerID, string eventName, bool isRemoteCall = false);
void RP_MoveToOtherInventory(int id, int invIndex, int invItemIndex, int newID, int newInvIndex, int newSlot, bool ignoreSlotTypes, bool isRemoteCall = false);
void RP_MoveWithinInventory(int id, int invIndex, int invItemIndex, int newSlot, bool ignoreSlotTypes, bool isRemoteCall = false);
void RP_MoveToWorld(int id, int invIndex, int invItemIndex, int itmWorldID, int grabUnitID, vector invItemMat[4], bool isRemoteCall = false);
void RP_MoveToInventory(int id, int invIndex, int slot, int itmID, bool ignoreSlotTypes, bool isRemoteCall = false);
bool CanMoveToOtherInventory(int id, int invIndex, int invItemIndex, int newID, int newInvIndex, int newSlot);
bool CanMoveWithinInventory(int id, int invIndex, int invItemIndex, int newSlot);
bool CanMoveToWorld(int id, int invIndex, int invItemIndex);
bool CanMoveToInventory(int id, int invIndex, int slot, int itmID);
#ifdef STEAMWORKS
string GetUniqueSteamUserID();
#endif
//! MULTIPLAYER: See comment in GameEntity class
void OnNetObjectInitSend( PacketOutputAdapter output );
void OnNetObjectInitReceived( PacketInputAdapter input );
void OnNetObjectAfterInitSend( PacketOutputAdapter output );
void OnNetObjectAfterInitReceived( PacketInputAdapter input );
void OnNetUpdate( PacketOutputAdapter output );
bool OnNetMessage( PacketInputAdapter input );
bool OnRPC(int proc, PacketInputAdapter input);
};
/*
//=================================================================
// campaign class
//=================================================================
class RoverMars_Campaign
{
Location locations[MAX_LOCATIONS];
int locationsCount;
Location currentLocation;
Location FindLocation(string name);
Location FindLocationNoCase(string name);
Location CreateLocation(string name);
void DestroyLocations();
void SetCurrentLocation(Location location);
void CreateLocations();
}
*/
//#include "scripts/campaign/VehicleSetupDecl.h" //vehicle setup object declarations
// Game definitions
#include "scripts/Campaign/GameDefsDecl.h"
// Conversation class
#include "scripts/Campaign/ConversationDecl.h"
//----------------------------------------------------------
void GameObject::GameObject()
{
type = GameObjectType;
}
//----------------------------------------------------------
void GameObject::~GameObject()
{
MPGameMode curmpmode = GetCurrentMPGameMode();
if (curmpmode)
curmpmode.OnDeleteClass(this);
}
//----------------------------------------------------------
Object_BuildingBlock GetBBlockByID(int id)
{
if (id <= 0)
return NULL;
if (!g_Game || !g_Game.CurrentWorld)
return NULL;
Object_BuildingBlock inbblock = (Object_BuildingBlock)FindEntityByID(g_Game.CurrentWorld, id);
if (inbblock)
return inbblock;
return NULL;
}
//----------------------------------------------------------
void STargetZone::STargetZone()
{
worldSTZone = NULL;
}
//----------------------------------------------------------
void STargetZone::~STargetZone()
{
}
//----------------------------------------------------------
void STargetZone::PrintData()
{
string zone = name + " coords = " + Vector2StringParse(coords) + " radius = " + ftoa(radius) + " height = " + ftoa(height);
Print(zone);
}
//----------------------------------------------------------
void STargetZone::SetOwnerPtr(ScienceTarget target)
{
owner = target;
}
//----------------------------------------------------------
void STargetZone::UpdateWorldSTZones()
{
ScienceTarget_Base stBase = (ScienceTarget_Base)worldSTZone;
if (stBase == NULL) {
if (owner.IsGenericType())
stBase = new ScienceTarget_Explore;
else {
if (owner.IsPhotoType())
stBase = new ScienceTarget_Photo;
else {
if (owner.IsAnalyzeType())
stBase = new ScienceTarget_Analyze;
}
}
worldSTZone = stBase;
SetOrigin(stBase, coords);
stBase.radius = radius;
stBase.height = height;
stBase.storageTarget = owner;
stBase.storageZone = owner.zones[zonenum];
} else {
coords = GetOrigin(stBase);
if (!owner.IsPhotoType()) {
radius = stBase.radius;
height = stBase.height;
} else {
stBase.radius = radius;
stBase.height = height;
}
}
}
//----------------------------------------------------------
void STargetZone::WriteScienceTargetsToSCN(int file, local int level)
{
string printStr = "";
for (int i = 0; i < level; i++) {
printStr += " ";
}
printStr += "$Zone ";
printStr += tostr(34) + Vector2StringParse(coords) + tostr(34) + " ";
printStr += ftoa(radius) + " ";
printStr += ftoa(height);
FPrintln(file, printStr);
}
//----------------------------------------------------------
void ScienceTarget::ScienceTarget()
{
type = ScienceTargetType;
}
//----------------------------------------------------------
void ScienceTarget::~ScienceTarget()
{
vehicle = NULL;
for(local int n = childTargetsCount - 1; n >= 0; n--)
{
local ScienceTarget child = childTargets[n];
if(child)
{
delete child;
child = NULL;
}
}
childTargetsCount = 0;
DestroyZones();
}
//----------------------------------------------------------
void ScienceTarget::SetEnabled(bool enable)
{
enabled = enable;
}
//----------------------------------------------------------
void ScienceTarget::SetVehicle(VehicleObject veh)
{
vehicle = veh;
}
//----------------------------------------------------------
bool ScienceTarget::GetInMission(ScienceTarget target)
{
ScienceTarget searchParent = parent;
while (searchParent != NULL) {
if (searchParent == target)
return true;
searchParent = searchParent.parent;
}
return false;
}
//----------------------------------------------------------
VehicleObject ScienceTarget::GetVehicle()
{
if(parent)
return parent.GetVehicle();
return vehicle;
}
//----------------------------------------------------------
string ScienceTarget::GetIcon()
{
if( IsPhotoType() )
return "set:rover_imageset image:camera";
if( IsAnalyzeType() )
return "set:rover_imageset image:instrument";
return "set:rover_imageset image:small_lander";
}
//----------------------------------------------------------
void ScienceTarget::UpdateSTVisualizers(bool show_sts, bool show_lnk, GameObject locSubEnt)
{
local int i;
local ScienceTarget_Base stBaseFrom, stBaseTo;
vector start, end;
// Go through and display links between zones, and show science target models
for (i = 0; i < zonesCount; i++) {
if (zones[i]) {
STargetZone zone = zones[i];
int nextZone = i + 1;
if (nextZone >= zonesCount)
nextZone = 0;
stBaseFrom = (ScienceTarget_Base)zone.worldSTZone;
if (show_sts)
stBaseFrom.UpdateModel(true);
else
stBaseFrom.UpdateModel(false);
if (nextZone != i && show_sts && show_lnk) {
zone = zones[nextZone];
stBaseTo = (ScienceTarget_Base)zone.worldSTZone;
start = GetOrigin(stBaseFrom) + Vector(0, 0, stBaseFrom.height * 0.5);
end = GetOrigin(stBaseTo) + Vector(0, 0, stBaseTo.height * 0.5);
stBaseFrom.UpdateLinkMarker(start, end);
} else
stBaseFrom.ClearLinkMarker();
}
}
local STargetZone zoneStart = zones[0];
local STargetZone zoneEnd;
stBaseFrom = (ScienceTarget_Base)zoneStart.worldSTZone;
// Go through targets that are to be enabled on completion, and show links to them
if (IsInherited(locSubEnt, Type("Location"))) {
Location loc = locSubEnt;
string tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens);
for(i = 0; i < MAX_SCIENCE_TARGET_ONCOMP; i++)
{
if (show_sts && show_lnk && i < numTokens) {
string onCompEnt = tokens[i];
if (strstr(onCompEnt, "ENTID") != -1) { // TKOM Entity
int len = strlen(onCompEnt);
int entNum = atoi(substr(onCompEnt, 5, len - 5));
if (entNum != -1) {
entNum = GetScnToGameIDFormat(entNum);
if (GetTKOMEntityByID(entNum) != NULL) {
TKOM_Entity tkomEnt = GetTKOMEntityByID(entNum);
start = GetOrigin(stBaseFrom) + Vector(0, 0, stBaseFrom.height * 0.5);
end = GetOrigin(tkomEnt);
stBaseFrom.UpdateOnCompLinkMarker(i, start, end);
} else
loc.RemoveOnCompST(onCompEnt);
} else
loc.RemoveOnCompST(onCompEnt);
} else { // ST
ScienceTarget targ = loc.FindScienceTarget(onCompEnt, true);
if (targ) {
for (int n = 0; n < childTargetsCount; n++) {
if (childTargets[n] == targ) {
targ = NULL; // If the on complete target is also a child, remove from on complete
n = childTargetsCount;
}
}
}
if (targ) {
zoneEnd = targ.zones[0];
stBaseTo = (ScienceTarget_Base)zoneEnd.worldSTZone;
start = GetOrigin(stBaseFrom) + Vector(0, 0, stBaseFrom.height * 0.5);
end = GetOrigin(stBaseTo) + Vector(0, 0, stBaseTo.height * 0.5);
stBaseFrom.UpdateOnCompLinkMarker(i, start, end);
} else
loc.RemoveOnCompST(onCompEnt);
}
} else
stBaseFrom.ClearOnCompLinkMarker(i);
}
}
// Tell all of our child targets to update their link markers as well, and show links to them
for (i = 0; i < MAX_SCIENCE_TARGET_CHILDS; i++) {
local ScienceTarget child = childTargets[i];
if (child) {
if (show_sts && show_lnk) {
zoneEnd = child.zones[0];
stBaseTo = (ScienceTarget_Base)zoneEnd.worldSTZone;
start = GetOrigin(stBaseFrom) + Vector(0, 0, stBaseFrom.height * 0.5);
end = GetOrigin(stBaseTo) + Vector(0, 0, stBaseTo.height * 0.5);
stBaseFrom.UpdateChildLinkMarker(i, start, end);
} else
stBaseFrom.ClearChildLinkMarker(i);
child.UpdateSTVisualizers(show_sts, show_lnk, locSubEnt);
} else
stBaseFrom.ClearChildLinkMarker(i);
}
}
//----------------------------------------------------------
bool ScienceTarget::IsParentedToTarget(ScienceTarget target)
{
if (target == NULL)
return false;
ScienceTarget chkTgt = parent;
while (chkTgt != NULL) {
chkTgt = chkTgt.parent;
if (chkTgt == target)
return true;
}
return false;
}
//----------------------------------------------------------
void ScienceTarget::PassChildrenToParent(GameObject locSubEnt)
{
local int i;
ScienceTarget child;
if (parent != NULL) {
for (i = 0; i < childTargetsCount; i++) {
if (childTargets[i]) {
child = childTargets[i];
child.parent = parent;
parent.RegisterChildTarget(childTargets[i]);
childTargets[i] = NULL;
}
}
} else {
if (IsInherited(locSubEnt, Type("Location"))) {
Location loc = locSubEnt;
for (i = 0; i < childTargetsCount; i++) {
if (childTargets[i]) {
child = childTargets[i];
child.parent = NULL;
loc.AddScienceTarget(childTargets[i]);
childTargets[i] = NULL;
}
}
}
}
}
//----------------------------------------------------------
bool ScienceTarget::RemoveChildTarget(ScienceTarget target)
{
if(!target)
return false;
local int i;
int remSlot = -1;
for (i = 0; i < MAX_SCIENCE_TARGET_CHILDS; i++) {
if (childTargets[i] == target) {
childTargets[i] = NULL;
remSlot = i;
i = MAX_SCIENCE_TARGET_CHILDS;
}
}
if (remSlot != -1) {
for (i = MAX_SCIENCE_TARGET_CHILDS - 1; i >= remSlot; i--) {
if (childTargets[i] != NULL) {
childTargets[remSlot] = childTargets[i];
childTargets[i] = NULL;
remSlot = i;
i = 0;
}
}
childTargetsCount--;
return true;
} else
return false;
}
//----------------------------------------------------------
void ScienceTarget::RegisterChildTarget(ScienceTarget child)
{
if(!child)
return;
childTargets[childTargetsCount] = child;
childTargetsCount++;
}
//----------------------------------------------------------
ScienceTarget ScienceTarget::FindChildTarget(local string name, local bool recursive)
{
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if(child.name == name)
return child;
if(recursive)
{
local ScienceTarget subChild = child.FindChildTarget(name, recursive);
if(subChild)
return subChild;
}
}
return NULL;
}
//----------------------------------------------------------
ScienceTarget ScienceTarget::FindChildTargetDuplicate(local string name, local bool recursive, int dupNum)
{
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if(child.name == name) {
gDuplicateSearch++;
if (gDuplicateSearch == dupNum)
return child;
}
if(recursive)
{
local ScienceTarget subChild = child.FindChildTargetDuplicate(name, recursive, dupNum);
if(subChild)
return subChild;
}
}
return NULL;
}
//----------------------------------------------------------
bool ScienceTarget::RemoveZone(STargetZone target)
{
if(!target)
return false;
local int i;
int remSlot = -1;
for (i = 0; i < MAX_SCIENCE_TARGET_ZONES; i++) {
if (zones[i] == target) {
zones[i] = NULL;
remSlot = i;
i = MAX_SCIENCE_TARGET_ZONES;
}
}
if (remSlot != -1) {
for (i = MAX_SCIENCE_TARGET_ZONES - 1; i >= remSlot; i--) {
if (zones[i] != NULL) {
zones[remSlot] = zones[i];
target = zones[remSlot];
target.zonenum = remSlot;
target.name = itoa(remSlot);
zones[i] = NULL;
remSlot = i;
i = 0;
}
}
zonesCount--;
return true;
} else
return false;
}
//----------------------------------------------------------
STargetZone ScienceTarget::CreateZone()
{
STargetZone zone = new STargetZone();
zone.SetOwnerPtr(this);
zone.name = itoa(zonesCount);
zone.zonenum = zonesCount;
zones[zonesCount] = zone;
zonesCount++;
return zone;
}
//----------------------------------------------------------
void ScienceTarget::DestroyZones()
{
for(int n = zonesCount - 1; n >= 0; n--)
{
STargetZone zone = zones[n];
if(zone)
{
delete zone;
zone = NULL;
}
zones[n] = NULL;
}
zonesCount = 0;
}
//----------------------------------------------------------
void ScienceTarget::DeleteWorldSTZones()
{
for(local int n = 0; n < zonesCount; n++)
{
STargetZone zone = zones[n];
if(zone && zone.worldSTZone)
{
delete zone.worldSTZone;
zone.worldSTZone = NULL;
}
}
for(n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if (child)
child.DeleteWorldSTZones();
}
}
//----------------------------------------------------------
bool ScienceTarget::IsGenericType()
{
return true;
}
//----------------------------------------------------------
bool ScienceTarget::IsPhotoType()
{
return false;
}
//----------------------------------------------------------
bool ScienceTarget::IsAnalyzeType()
{
return false;
}
//----------------------------------------------------------
void ScienceTarget::PrintGenericData()
{
string line;
Print("");
Print("---------------------------------");
Print(String("STarget: " + name));
Print(priority);
Print(worth);
Print(enabled);
Print(onComplEnable);
for(int n = 0; n < zonesCount; n++)
{
STargetZone zone = zones[n];
zone.PrintData();
}
}
//----------------------------------------------------------
void ScienceTarget::PrintData()
{
PrintGenericData();
}
//----------------------------------------------------------
int ScienceTarget::GetOnCompNum()
{
string st_oncompl_tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, st_oncompl_tokens);
return numTokens;
}
//----------------------------------------------------------
bool ScienceTarget::FindOnComp(string onCompST)
{
string st_oncompl_tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, st_oncompl_tokens);
for(int i = 0; i < numTokens; i++)
{
if (st_oncompl_tokens[i] == onCompST)
return true;
}
return false;
}
//----------------------------------------------------------
void ScienceTarget::RemoveOnComp(string onCompST)
{
string tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens);
onComplEnable = "";
for(int i = 0; i < numTokens; i++)
{
if(tokens[i] != "" && tokens[i] != onCompST) {
onComplEnable += " ";
onComplEnable += tokens[i];
}
}
}
//----------------------------------------------------------
void ScienceTarget::RemoveOnCompST(string onCompST)
{
local int i;
string tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens);
onComplEnable = "";
for(i = 0; i < numTokens; i++)
{
if(tokens[i] != "" && tokens[i] != onCompST) {
onComplEnable += " ";
onComplEnable += tokens[i];
}
}
for (i = 0; i < childTargetsCount; i++) {
ScienceTarget child = childTargets[i];
child.RemoveOnCompST(onCompST);
}
}
//----------------------------------------------------------
void ScienceTarget::EnableOnCompSTs(Location curLoc)
{
// Enable all STs that are linked as On Complete
if(curLoc)
{
local string tokens2[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens2);
for(local int n2 = 0; n2 < numTokens; n2++)
{
string onCompEnt = tokens2[n2];
if (strstr(onCompEnt, "ENTID") != -1) { // TKOM Entity
int len = strlen(onCompEnt);
int entNum = atoi(substr(onCompEnt, 5, len - 5));
if (entNum != -1) {
entNum = GetScnToGameIDFormat(entNum);
if (GetTKOMEntityByID(entNum) != NULL) {
TKOM_Entity tkomEnt = GetTKOMEntityByID(entNum);
if (IsInherited(tkomEnt, Type("Event_Base"))) {
Event_Base evEnt = tkomEnt;
evEnt.TriggerEvent();
}
}
}
} else { // ST
ScienceTarget targ = curLoc.FindScienceTarget(tokens2[n2], true);
if(targ)
targ.SetEnabled(true);
}
}
}
// Enable all child targets
for (int i = 0; i < MAX_SCIENCE_TARGET_CHILDS; i++) {
if (childTargets[i]) {
ScienceTarget child = childTargets[i];
child.SetEnabled(true);
}
}
}
//----------------------------------------------------------
void ScienceTarget::AddOnComp(string onCompST)
{
if(onComplEnable != "")
onComplEnable += " ";
onComplEnable += onCompST;
}
//----------------------------------------------------------
float ScienceTarget::GetCompletion()
{
if(zonesCount == 0)
return 0;
float sum = 0;
for(int n = 0; n < zonesCount; n++)
{
STargetZone zone = zones[n];
sum += zone.completion;
}
return sum / (float)zonesCount;
}
//----------------------------------------------------------
ScienceTarget ScienceTarget::GetMissionParent(ScienceTarget sTarget)
{
if (!parent)
return sTarget;
else {
sTarget = sTarget.parent;
while (sTarget.parent) {
sTarget = sTarget.parent;
}
return sTarget;
}
}
//----------------------------------------------------------
float ScienceTarget::GetMissionCompletion(int prioFilter)
{
local int numComp = 0;
local float result = 0;
if (prioFilter == -1 || priority == prioFilter) {
result = GetCompletion();
numComp = 1;
}
if (childTargetsCount > 0) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget child = childTargets[i];
local vector resVec = child.GetMissionSubTgtCompletion(prioFilter);
result += resVec[0];
numComp += floor(resVec[1]);
}
}
if (numComp > 0) {
result *= 1 / numComp;
return result;
} else
return -1;
}
//----------------------------------------------------------
vector ScienceTarget::GetMissionSubTgtCompletion(int prioFilter)
{
local float resultX = 0;
local float resultY = 0;
if (prioFilter == -1 || priority == prioFilter) {
resultX = GetCompletion();
resultY = 1;
}
if (childTargetsCount > 0) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget child = childTargets[i];
local vector resVec = child.GetMissionSubTgtCompletion(prioFilter);
resultX = resultX + resVec[0];
resultY = resultY + resVec[1];
}
}
return Vector(resultX, resultY, 0);
}
//----------------------------------------------------------
string ScienceTarget::GetWorthText()
{
return "$" + itoa(worth) + "k";
}
//----------------------------------------------------------
string ScienceTarget::GetPriorityText()
{
return ST_PRIORITIES[priority];
}
//----------------------------------------------------------
string ScienceTarget::GetMissionPriorityText()
{
return ST_PRIORITIES[mission_priority];
}
//----------------------------------------------------------
int ScienceTarget::GetNumValidPresets()
{
local int result = 0;
for(local int n = 0; n < g_Defs.existingVehicleDefsCount; n++)
{
local VehicleDef def = g_Defs.existingVehicleDefs[n];
if (def.CanCompleteMission(this, owner)
result++;
}
return result;
}
//----------------------------------------------------------
int ScienceTarget::GetNumValidVehicles()
{
local int result = 0;
for(local int n = 0; n < owner.vehiclesCount; n++)
{
local VehicleObject veh = owner.vehicles[n];
if (veh.CanCompleteMission(this, owner)
result++;
}
return result;
}
//----------------------------------------------------------
void ScienceTarget::ClearMissionData()
{
mission_title = "";
mission_description = "";
mission_result = "";
mission_globalObjectives = "";
mission_priority = ST_P_INVALID;
mission_worth_major = 0;
mission_worth_minor = 0;
mission_budgetGiven_major = false;
mission_budgetGiven_minor = false;
mission_budgetGiven_negligible = false;
mission_mobilityRequired = false;
mission_generatedByVehicleName = "";
}
//----------------------------------------------------------
void ScienceTarget::GenerateDefaultMissionData()
{
mission_title = "#tkom_stdefmis_tit " + itoa(rand(0, 10)) + itoa(rand(0, 10)) + itoa(rand(0, 10)) + itoa(rand(0, 10));
mission_description = "#tkom_stdefmis_desc";
mission_result = "#tkom_stdefmis_res";
mission_globalObjectives = "";
mission_priority = ST_P_MINOR;
mission_worth_major = 50;
mission_worth_minor = 10;
mission_budgetGiven_major = false;
mission_budgetGiven_minor = false;
mission_budgetGiven_negligible = false;
mission_mobilityRequired = false;
mission_generatedByVehicleName = "";
}
//----------------------------------------------------------
void ScienceTarget::GenerateDefaultData(vector pos, ScienceTarget ownEnt)
{
priority = ST_P_MAJOR;
worth = 5;
enabled = true;
onComplEnable = "";
CreateZone();
STargetZone zOne = zones[0];
zOne.coords = pos;
if (IsGenericType()) {
title = "#tkom_stdef_tit_exp";
description = "#tkom_stdef_desc_exp0" + itoa(rand(1, 6));
zOne.radius = 320;
zOne.height = 320;
}
if (IsPhotoType()) {
title = "#tkom_stdef_tit_pht";
description = "#tkom_stdef_desc_pht0" + itoa(rand(1, 6));
zOne.radius = 16;
zOne.height = 32;
ScienceTargetPhoto spwnST_Pht = ownEnt;
spwnST_Pht.minIncNum = 1;
spwnST_Pht.colorCameraReq = false;
}
if (IsAnalyzeType()) {
title = "#tkom_stdef_tit_anz";
description = "#tkom_stdef_desc_anz0" + itoa(rand(1, 6));
zOne.radius = 320;
zOne.height = 320;
ScienceTargetAnalyze spwnST_Anz = ownEnt;
spwnST_Anz.physMat = MATERIAL_STONE;
spwnST_Anz.specMat = "";
}
zOne.completion = 0;
}
//----------------------------------------------------------
int ScienceTarget::GetMissionTargetsTotal(bool onlyEnabled, bool onlyIncomplete)
{
local int result = 0;
if (!onlyEnabled || enabled) {
if (!onlyIncomplete || GetCompletion() < 1)
result++;
}
if (childTargetsCount > 0) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget child = childTargets[i];
result += child.GetMissionTargetsTotal(onlyEnabled, onlyIncomplete);
}
}
return result;
}
//----------------------------------------------------------
// NOTE: Had to add the first target as an input parameter as a disghusting hack to overcome not being able to use 'this'
ScienceTarget ScienceTarget::GetMissionTargetByNum(ScienceTarget firstTgt, int countUp, int stNum, bool onlyEnabled, bool onlyIncomplete)
{
ScienceTarget result = firstTgt;
if (!onlyEnabled || enabled) {
if (!onlyIncomplete || GetCompletion() < 1) {
if (countUp == stNum) return firstTgt;
countUp++;
}
}
if (childTargetsCount > 0) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget child = childTargets[i];
result = child.GetMissionTargetByNum(child, countUp, stNum, onlyEnabled, onlyIncomplete);
if (result) return result;
}
}
return NULL;
}
//----------------------------------------------------------
void ScienceTarget::ClearCompletion()
{
mission_budgetGiven_major = false;
mission_budgetGiven_minor = false;
mission_budgetGiven_negligible = false;
for(int n = 0; n < zonesCount; n++)
{
STargetZone zone = zones[n];
zone.completion = 0;
}
}
//----------------------------------------------------------
void ScienceTarget::DoAnalysis(TKOM_Entity vehicle, string instSubType, int physMat, string specMat, vector pos)
{
local int n;
if (IsAnalyzeType()) {
for(n = 0; n < zonesCount; n++)
{
STargetZone zone = zones[n];
ScienceTarget_Base stBase = (ScienceTarget_Base)zone.worldSTZone;
if (stBase)
stBase.Analyze(vehicle, instSubType, physMat, specMat, pos);
}
}
for(n = 0; n < childTargetsCount; n++)
{
ScienceTarget child = childTargets[n];
child.DoAnalysis(vehicle, instSubType, physMat, specMat, pos);
}
}
//----------------------------------------------------------
void ScienceTarget::DoPhoto(TKOM_Entity vehicle, int camNum, vector camPos, bool color)
{
local int n;
if (IsPhotoType()) {
int zonesVisible[MAX_SCIENCE_TARGET_ZONES];
int numZonesVisible = 0;
STargetZone zone;
ScienceTarget_Base stBase;
// First determine which zones are visible
for(n = 0; n < zonesCount; n++)
{
bool visible = false;
zone = zones[n];
stBase = (ScienceTarget_Base)zone.worldSTZone;
if (stBase)
visible = stBase.GetPhotoZone(camNum, camPos, color);
if (visible) {
zonesVisible[numZonesVisible] = n;
numZonesVisible++;
}
}
// Get the screen scale size for the zones
vector mins = ZeroVec;
vector maxs = ZeroVec;
float mainWidth, mainHeight, width, height, x, y;
int screenX, screenY;
GetScreenSize(screenX, screenY);
mainWidth = fsum(screenX);
mainHeight = fsum(screenY);
vector validMins = Vector(mainWidth * ST_PHOTOFRAMEBOUNDS, mainHeight * ST_PHOTOFRAMEBOUNDS, 0);
vector validMaxs = Vector(1 - ST_PHOTOFRAMEBOUNDS * mainWidth, 1 - ST_PHOTOFRAMEBOUNDS * mainHeight, 0);
int zNum;
for(n = 0; n < numZonesVisible; n++)
{
zNum = zonesVisible[n];
zone = zones[zNum];
vector screenPos = Get2DHUDPos(camNum, zone.coords);
bool validX = false;
bool validY = false;
if (screenPos[0] > validMins[0] && validMaxs[0] > screenPos[0])
validX = true;
if (screenPos[1] > validMins[1] && validMaxs[1] > screenPos[1])
validY = true;
if (mins == ZeroVec && maxs == ZeroVec && validX && validY) {
mins[0] = screenPos[0];
mins[1] = screenPos[1];
maxs[0] = screenPos[0];
maxs[1] = screenPos[1];
}
if (mins[0] > screenPos[0] && validX && validY)
mins[0] = screenPos[0];
if (mins[1] > screenPos[1] && validX && validY)
mins[1] = screenPos[1];
if (maxs[0] < screenPos[0] && validX && validY)
maxs[0] = screenPos[0];
if (maxs[1] < screenPos[1] && validX && validY)
maxs[1] = screenPos[1];
}
int posX = floor(mins[0]);
int posY = floor(mins[1]);
int posX2 = floor(maxs[0]) - posX;
int posY2 = floor(maxs[1]) - posY;
float screenScale = posX2 / mainWidth;
screenScale *= posY2 / mainHeight;
screenScale *= 1000;
ScienceTargetPhoto targetPht = (ScienceTargetPhoto)stBase.storageTarget;
bool viewTooSmall = false;
if (targetPht.minIncNum > 1 && screenScale < ST_PHOTOMINSCREENSCALE)
viewTooSmall = true;
// Now increment if minimum visible zones is correct and the view is not too small
if (!viewTooSmall) {
for(n = 0; n < numZonesVisible; n++)
{
zNum = zonesVisible[n];
zone = zones[zNum];
stBase = (ScienceTarget_Base)zone.worldSTZone;
if (stBase)
stBase.Photo(vehicle, camNum, camPos, numZonesVisible);
}
}
}
for(n = 0; n < childTargetsCount; n++)
{
ScienceTarget child = childTargets[n];
child.DoPhoto(vehicle, camNum, camPos, color);
}
}
//----------------------------------------------------------
void ScienceTarget::UpdateWorldSTZones()
{
local int n;
for(n = 0; n < zonesCount; n++)
{
STargetZone zone = zones[n];
zone.UpdateWorldSTZones();
}
if (childTargetsCount > 0) {
for(n = 0; n < childTargetsCount; n++)
{
ScienceTarget child = childTargets[n];
child.UpdateWorldSTZones();
}
}
}
//----------------------------------------------------------
void ScienceTarget::WriteScienceMissionToSCN(int file, string startAdd)
{
FPrintln(file, String(startAdd + "Mission_Title " + tostr(34) + mission_title + tostr(34)));
FPrintln(file, String(startAdd + "Mission_Description " + tostr(34) + mission_description + tostr(34)));
FPrintln(file, String(startAdd + "Mission_Result " + tostr(34) + mission_result + tostr(34)));
FPrintln(file, String(startAdd + "Mission_GlobalObjectives " + tostr(34) + mission_globalObjectives + tostr(34)));
FPrintln(file, String(startAdd + "Mission_Priority " + ST_PRIORITIES[mission_priority]));
FPrintln(file, String(startAdd + "Mission_WorthMajor " + itoa(mission_worth_major)));
FPrintln(file, String(startAdd + "Mission_WorthMinor " + itoa(mission_worth_minor)));
FPrintln(file, String(startAdd + "Mission_MobilityReq " + itoa(mission_mobilityRequired)));
}
//----------------------------------------------------------
void ScienceTarget::WriteScienceTargetsToSCN(int file, local int level)
{
if (IsGenericType()) {
local int i;
string startAdd = "";
string startEntAdd = "";
for (i = 0; i < level; i++) {
startAdd += " ";
startEntAdd += "++ ";
}
FPrintln(file, String(startAdd + "//-------------------------------------------"));
FPrintln(file, String(startEntAdd + "$ExploreTarget " + tostr(34) + name + tostr(34)));
FPrintln(file, String(startAdd + "Title " + tostr(34) + title + tostr(34)));
FPrintln(file, String(startAdd + "Description " + tostr(34) + description + tostr(34)));
FPrintln(file, String(startAdd + "Priority " + ST_PRIORITIES[priority]));
FPrintln(file, String(startAdd + "Worth " + itoa(worth)));
if (enabled)
FPrintln(file, String(startAdd + "Enabled 1"));
else
FPrintln(file, String(startAdd + "Enabled 0"));
if (parent == NULL)
WriteScienceMissionToSCN(file, startAdd);
for(i = 0; i < zonesCount; i++)
{
STargetZone zone = zones[i];
zone.WriteScienceTargetsToSCN(file, level);
}
string tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens);
for(i = 0; i < numTokens; i++)
{
FPrintln(file, String(startAdd + "OnComplEnable " + tostr(34) + tokens[i] + tostr(34)));
}
if (childTargetsCount > 0) {
level++;
for (i = 0; i < childTargetsCount; i++) {
local ScienceTarget stEnt = childTargets[i];
stEnt.WriteScienceTargetsToSCN(file, level);
}
}
}
}
//----------------------------------------------------------
void ScienceTargetAnalyze::WriteScienceTargetsToSCN(int file, local int level)
{
if (IsAnalyzeType()) {
local int i;
string startAdd = "";
string startEntAdd = "";
for (i = 0; i < level; i++) {
startAdd += " ";
startEntAdd += "++ ";
}
FPrintln(file, String(startAdd + "//-------------------------------------------"));
FPrintln(file, String(startEntAdd + "$AnalyzeTarget " + tostr(34) + name + tostr(34)));
FPrintln(file, String(startAdd + "Title " + tostr(34) + title + tostr(34)));
FPrintln(file, String(startAdd + "Description " + tostr(34) + description + tostr(34)));
FPrintln(file, String(startAdd + "Priority " + ST_PRIORITIES[priority]));
FPrintln(file, String(startAdd + "Worth " + itoa(worth)));
if (enabled)
FPrintln(file, String(startAdd + "Enabled 1"));
else
FPrintln(file, String(startAdd + "Enabled 0"));
FPrintln(file, String(startAdd + "PhysMat " + tostr(34) + MATERIAL_LIST[physMat] + tostr(34)));
FPrintln(file, String(startAdd + "SpecMat " + tostr(34) + specMat + tostr(34)));
FPrintln(file, String(startAdd + "SpecInst " + tostr(34) + specInst + tostr(34)));
if (parent == NULL)
WriteScienceMissionToSCN(file, startAdd);
for(i = 0; i < zonesCount; i++)
{
STargetZone zone = zones[i];
zone.WriteScienceTargetsToSCN(file, level);
}
string tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens);
for(i = 0; i < numTokens; i++)
{
FPrintln(file, String(startAdd + "OnComplEnable " + tostr(34) + tokens[i] + tostr(34)));
}
if (childTargetsCount > 0) {
level++;
for (i = 0; i < childTargetsCount; i++) {
local ScienceTarget stEnt = childTargets[i];
stEnt.WriteScienceTargetsToSCN(file, level);
}
}
}
}
//----------------------------------------------------------
void ScienceTargetPhoto::WriteScienceTargetsToSCN(int file, local int level)
{
if (IsPhotoType()) {
local int i;
string startAdd = "";
string startEntAdd = "";
for (i = 0; i < level; i++) {
startAdd += " ";
startEntAdd += "++ ";
}
FPrintln(file, String(startAdd + "//-------------------------------------------"));
FPrintln(file, String(startEntAdd + "$PhotoTarget " + tostr(34) + name + tostr(34)));
FPrintln(file, String(startAdd + "Title " + tostr(34) + title + tostr(34)));
FPrintln(file, String(startAdd + "Description " + tostr(34) + description + tostr(34)));
FPrintln(file, String(startAdd + "Priority " + ST_PRIORITIES[priority]));
FPrintln(file, String(startAdd + "Worth " + itoa(worth)));
if (enabled)
FPrintln(file, String(startAdd + "Enabled 1"));
else
FPrintln(file, String(startAdd + "Enabled 0"));
FPrintln(file, String(startAdd + "MinIncNum " + itoa(minIncNum)));
if (colorCameraReq)
FPrintln(file, String(startAdd + "ColorCameraReq 1"));
else
FPrintln(file, String(startAdd + "ColorCameraReq 0"));
if (parent == NULL)
WriteScienceMissionToSCN(file, startAdd);
for(i = 0; i < zonesCount; i++)
{
STargetZone zone = zones[i];
zone.WriteScienceTargetsToSCN(file, level);
}
string tokens[MAX_SCIENCE_TARGET_ONCOMP];
int numTokens = ParseString(onComplEnable, tokens);
for(i = 0; i < numTokens; i++)
{
FPrintln(file, String(startAdd + "OnComplEnable " + tostr(34) + tokens[i] + tostr(34)));
}
if (childTargetsCount > 0) {
level++;
for (i = 0; i < childTargetsCount; i++) {
local ScienceTarget stEnt = childTargets[i];
stEnt.WriteScienceTargetsToSCN(file, level);
}
}
}
}
//----------------------------------------------------------
void ScienceTargetPhoto::ScienceTargetPhoto()
{
}
//----------------------------------------------------------
bool ScienceTargetPhoto::IsPhotoType()
{
return true;
}
//----------------------------------------------------------
bool ScienceTargetPhoto::IsGenericType()
{
return false;
}
//----------------------------------------------------------
void ScienceTargetPhoto::PrintData()
{
PrintGenericData();
Print(minIncNum);
Print(colorCameraReq);
}
//----------------------------------------------------------
void ScienceTargetAnalyze::ScienceTargetAnalyze()
{
}
//----------------------------------------------------------
bool ScienceTargetAnalyze::IsAnalyzeType()
{
return true;
}
//----------------------------------------------------------
bool ScienceTargetAnalyze::IsGenericType()
{
return false;
}
//----------------------------------------------------------
bool ScienceTargetAnalyze::IsInstrumentInList(string instSubType)
{
if (specInst == "")
return true;
string tokens[MAX_SCIENCE_TARGET_ANZ_SPECINST];
// Parse through and extract valid instruments data
int numTokens = ParseString(specInst, tokens);
for (int i = 0; i < numTokens; i++) {
if (tokens[i] == instSubType)
return true;
}
return false;
}
//----------------------------------------------------------
int ScienceTargetAnalyze::GetNumInstruments()
{
if (specInst == "")
return 0;
string tokens[MAX_SCIENCE_TARGET_ANZ_SPECINST];
int numTokens = ParseString(specInst, tokens);
return numTokens;
}
//----------------------------------------------------------
string ScienceTargetAnalyze::GetInstrument(int numInList)
{
if (specInst == "")
return "";
string tokens[MAX_SCIENCE_TARGET_ANZ_SPECINST];
int numTokens = ParseString(specInst, tokens);
if (numInList >= MAX_SCIENCE_TARGET_ANZ_SPECINST)
return "";
else
return tokens[numInList];
}
//----------------------------------------------------------
void ScienceTargetAnalyze::PrintData()
{
PrintGenericData();
Print(physMat);
Print(specMat);
Print(specInst);
}
//----------------------------------------------------------
bool ScienceTarget::IsCurrentlyCompletable()
{
if(!enabled)
return false;
if( GetMissionCompletion(ST_P_ALL) >= 1)
return false;
if( mission_generatedByVehicleName != "")
return false;
if ( GetNumValidPresets() == 0 && GetNumValidVehicles() == 0 )
return false;
// Major targets incomplete and cannot complete them
if ( GetMissionCompletion(ST_P_MAJOR) < 1 && !HasTechForTarget(true, ST_P_MAJOR, false) )
return false;
// Major targets complete and cannot complete any remaining targets
if ( GetMissionCompletion(ST_P_MAJOR) >= 1 && !HasTechForTarget(true, ST_P_ALL, true) )
return false;
return true;
}
//----------------------------------------------------------
bool ScienceTarget::HasTechForTarget(bool recursive, int prioFilter, bool anyAtAllMode)
{
string parts_types[ALL_INSTRUMENTS_MAX];
string parts_subtypes[ALL_INSTRUMENTS_MAX];
int parts_num = 0;
for (int i = 0; i < ALL_INSTRUMENTS_MAX; i++)
{
parts_types[i] = "";
parts_subtypes[i] = "";
}
InstrumentDef instList[ALL_INSTRUMENTS_MAX];
int numInsts = g_Defs.FillTechAvailableInstList(instList);
for (i = 0; i < numInsts; i++)
{
InstrumentDef inst = instList[i];
for (int n = 0; n < inst.partsCount; n++)
{
PartDef part = inst.parts[n];
bool inList = false;
for (int p = 0; p < parts_num; p++)
{
if (part.type == parts_types[p] && part.subtype == parts_subtypes[p]) {
inList = true;
break;
}
}
if (!inList) {
parts_types[parts_num] = part.type;
parts_subtypes[parts_num] = part.subtype;
parts_num++;
}
}
}
return GetValidInstruments(parts_types, parts_subtypes, parts_num, recursive, prioFilter, anyAtAllMode);
}
//----------------------------------------------------------
bool ScienceTarget::GetValidInstruments(string parts_types[], string parts_subtypes[], int parts_num, bool recursive, int prioFilter, bool anyAtAllMode)
{
if (childTargetsCount > 0 && recursive) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget stEnt = childTargets[i];
local bool isValidInst = stEnt.GetValidInstruments(parts_types, parts_subtypes, parts_num, recursive, prioFilter, anyAtAllMode);
if (!anyAtAllMode && !isValidInst)
return false;
if (anyAtAllMode && isValidInst)
return true;
}
}
if (anyAtAllMode && GetCompletion() == 1)
return false;
else
return true;
}
//----------------------------------------------------------
bool ScienceTargetAnalyze::GetValidInstruments(string parts_types[], string parts_subtypes[], int parts_num, bool recursive, int prioFilter, bool anyAtAllMode)
{
local bool result = false;
bool skip = false;
if (prioFilter != -1 && priority != prioFilter)
skip = true;
if (specInst == "" || skip)
result = true;
else {
string instList_ST[MAX_SCIENCE_TARGET_ANZ_SPECINST];
int numTokens = ParseString(specInst, instList_ST);
for (local int n = 0; n < parts_num; n++) {
if (parts_types[n] == "Instrument" || parts_types[n] == "InstrumentPassive") {
for (local int p = 0; p < numTokens; p++) {
if (instList_ST[p] == parts_subtypes[n]) {
result = true;
n = parts_num;
p = numTokens;
}
}
}
}
}
if (childTargetsCount > 0 && recursive) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget stEnt = childTargets[i];
local bool isValidInst = stEnt.GetValidInstruments(parts_types, parts_subtypes, parts_num, recursive, prioFilter, anyAtAllMode);
if (!anyAtAllMode && !isValidInst)
return false;
if (anyAtAllMode && isValidInst)
return true;
}
}
if (anyAtAllMode && GetCompletion() == 1)
return false;
else
return result;
}
//----------------------------------------------------------
bool ScienceTargetPhoto::GetValidInstruments(string parts_types[], string parts_subtypes[], int parts_num, bool recursive, int prioFilter, bool anyAtAllMode)
{
local bool result = false;
if (prioFilter != -1 && priority != prioFilter)
result = true;
else {
for (local int n = 0; n < parts_num; n++) {
if (parts_types[n] == "Camera" || parts_types[n] == "CameraBW") {
if (!colorCameraReq || parts_types[n] == "Camera") {
result = true;
n = parts_num;
}
}
}
}
if (childTargetsCount > 0 && recursive) {
for (local int i = 0; i < childTargetsCount; i++) {
local ScienceTarget stEnt = childTargets[i];
local bool isValidInst = stEnt.GetValidInstruments(parts_types, parts_subtypes, parts_num, recursive, prioFilter, anyAtAllMode);
if (!anyAtAllMode && !isValidInst)
return false;
if (anyAtAllMode && isValidInst)
return true;
}
}
if (anyAtAllMode && GetCompletion() == 1)
return false;
else
return result;
}
//----------------------------------------------------------
void RagdollObject::ClearData()
{
int i;
scriptPath = "";
for (i = 0; i < RAGDOLL_MAXJOINTS; i++)
{
joints_angles[i] = ZeroVec;
joints_limits_lo[i] = ZeroVec;
joints_limits_hi[i] = ZeroVec;
joints_spring_stiff[i] = 0;
joints_spring_damp[i] = 0;
joints_part1[i] = -1;
joints_part2[i] = -1;
}
for (i = 0; i < RAGDOLL_MAXBLOCKS; i++)
{
blocks_part1[i] = -1;
blocks_part2[i] = -1;
}
for (i = 0; i < RAGDOLL_MAXPARTS; i++)
{
parts_mass[i] = -1;
parts_models[i] = "";
parts_name[i] = "";
parts_static[i] = false;
parts_nophys[i] = false;
parts_pos[i] = ZeroVec;
parts_ang[i] = ZeroVec;
parts_wmat0[i] = ZeroVec;
parts_wmat1[i] = ZeroVec;
parts_wmat2[i] = ZeroVec;
parts_wmat3[i] = ZeroVec;
parts_velLin[i] = ZeroVec;
parts_velAng[i] = ZeroVec;
parts_conPtcSnd[i] = "";
}
for (i = 0; i < RAGDOLL_GENVARS; i++)
{
GenFloats[i] = 0;
GenInts[i] = 0;
GenVecs[i] = ZeroVec;
GenStrings[i] = "";
}
joints_num = 0;
blocks_num = 0;
parts_num = 0;
}
//----------------------------------------------------------
void RagdollObject::RagdollObject()
{
ClearData();
NoStore = false;
ragdollHandler = NULL;
cfgFile = "";
interactionLayer = COLLIDERLAYER_DYNAMIC;
MatrixIdentity(CompatibilitySpawnMat);
Store_ID = 0;
}
//----------------------------------------------------------
void RagdollObject::~RagdollObject()
{
// If linked to a character, remove link
if (!g_Game.IsClient() && Store_OwnerID > 0)
{
VehicleObject charBase = owner.FindVehicleByStoreID(Store_OwnerID);
if (charBase && charBase.isCharacter)
{
CharacterObject character = (CharacterObject)charBase;
if (character.Ragdoll_ID == Store_ID)
character.Ragdoll_ID = 0;
}
}
}
//----------------------------------------------------------
void VehicleObject::VehicleObject()
{
ClearData();
type = VehicleObjectType;
NoStore = false;
NoCompatRespawn = false;
Owner_SteamID = "";
Owner_SteamName = "";
MatrixIdentity(CompatibilitySpawnMat);
isMobile = false;
isSpace = false;
isGround = false;
isCharacter = false;
isNotSelectable = false;
noPhotos = false;
ConsoleControl = false;
ManualInputEnabled = true;
LowPowerNotifiedLevel = 1;
LandingManual = false;
genMis_AllowGenerate = false;
genMis_NoMisCheckInterval = 0;
if (g_Campaign.campaignIndex == CAMPAIGN_SPACE_PROGRAM)
genMis_AllowGenerate = true;
SetDayZero();
Agency_VehicleProfit = 0;
Agency_VehicleMissionsCompleted_Major = 0;
Agency_VehicleMissionsCompleted_Minor = 0;
Agency_VehicleMissionsCompleted_Negligible = 0;
metersDriven = 0;
metersDrivenSol = 0;
currentSol = 0;
landing_totaltime = 0;
landing_manualtime = 0;
landing_landedOnce = false;
Agency_MisCost = 0;
CustomWaypoint = ZeroVec;
CustomDir = ZeroVec;
followCharacter = NULL;
interactionLayer = COLLIDERLAYER_VEHICLE;
Team = TEAM_DEFAULT;
Store_ID = 0;
}
//----------------------------------------------------------
void VehicleObject::DisembarkAll()
{
for (int i = 0; i < passengerSeat_num; i++)
{
CharacterObject charObj = passengers[i];
if (charObj) {
charObj.DisembarkVehicle();
charObj.MovementState = CHAR_MOVESTATE_STANDING;
}
passengers[i] = NULL;
}
}
//----------------------------------------------------------
void CharacterObject::CharacterObject()
{
noViewFocus = false;
noMovement = false;
noInventoryToggle = false;
Ragdoll_ID = 0;
isCharacter = true;
inVehicle = NULL;
inVehicleSeat = -1;
Health = 1;
LungsAirTime = CHAR_LUNGSAIR_MAX;
Stance = CHAR_STANCE_UPRIGHT;
HeartBPM = CHAR_HEARTRATE_DEFAULT;
RespBPM = CHAR_RESPRATE_DEFAULT;
StunnedTime = 0;
DeadTime = 0;
MovementState = CHAR_MOVESTATE_STANDING;
HoldObjectID = 0;
HoldObjectSubID = 0;
TraceObjectID = 0;
TraceObjectSubID = 0;
ToolEquipped = false;
ToolPartIndex = -1;
ToolItem = NULL;
CurrentAnimation = "";
ClearCustomAnimation();
SurvivalDefaults();
ClearAdditionalSlotHighlights();
}
//----------------------------------------------------------
void CharacterObject::~CharacterObject()
{
CharacterObject selfChar = NULL;
DisembarkVehicle();
DisembarkBBlock();
// First find self ('this' here is a reference to the campaign, script issue)
VehicleObject selfVeh = owner.FindVehicle(name);
if (selfVeh)
selfChar = (CharacterObject)selfVeh;
// Go through all vehicle objects and remove follow link to this character
for (int i = 0; i < owner.vehiclesCount; i++) {
VehicleObject veh = owner.vehicles[i];
if (veh && veh.followCharacter == selfChar)
veh.followCharacter = NULL;
}
// If has an active ragdoll, delete it too
if (GetInRagdoll() && !g_Game.IsClient())
{
RagdollObject ragdollStore = owner.FindRagdollByStoreID(Ragdoll_ID);
Ragdoll_ID = 0;
if (ragdollStore)
{
Ragdoll_Handler ragdoll = ragdollStore.ragdollHandler;
if (ragdoll)
{
ragdoll.DeleteStorage();
delete ragdoll;
}
}
}
}
//----------------------------------------------------------
void VehicleObject::~VehicleObject()
{
UndockAll();
DisembarkAll();
if(mission)
{
mission.SetVehicle(NULL); //NULL pointer in mission before destroy
mission = NULL;
}
DestroyPhotos(false);
DestroyLogoutPhoto(false);
DestroyInventories();
}
//----------------------------------------------------------
void VehicleObject::SetReentryPos(vector pos)
{
ReentryZone = pos;
}
//----------------------------------------------------------
void VehicleObject::SetDefinitionFile(string fileName)
{
defFile = fileName;
}
//----------------------------------------------------------
VehicleDef VehicleObject::FindDefinition()
{
return g_Defs.FindExistingVehicleDefByConfig(defFile);
}
//----------------------------------------------------------
string VehicleObject::GetStatusText()
{
float damage = parts_damage[0];
string statusName;
if(damage < 0.5)
statusName = "#tkom_status_1";
else
{
if(damage > 0.8)
statusName = "#tkom_status_3";
else
statusName = "#tkom_status_2";
}
return statusName;
}
//----------------------------------------------------------
void VehicleObject::ClearData()
{
int i;
MatrixIdentity(UnitMapMatrix);
PowerLevel = 1.0; // The vehicle should be fully charged on start
SystemsActivated = true;
LandingActivated = true;
HUDType = 0; // Set HUD type to Ground by default
NightVision = false;
ThermalVisionMode = 0;
NightCamLEDs = false;
NightCamLEDPart = -1;
MouseControlPri = false;
LandingZone = ZeroVec;
ReentryZone = ZeroVec;
ReentryVelocity = ZeroVec;
tabs_update = false;
tabs_framepos = 0;
tabs_nav_WPDist = 2;
tabs_nav_WPPrio = 2;
tabs_nav_WPMis = 1;
tabs_nav_WPTask = -1;
cams_framepos = 0;
cams_mainMode = 0;
cams_3rdAngles = "30 0 0.2";
cams_3rdAngles2 = "30 0 0.2";
CurrentPriPart = 0;
CurrentSecPart = 0;
CurrentInstrument = -1;
CurrentHUDMode = 0;
CurrentCamera = 0;
//Modular GUI variables
tabs_opened = 0;
tabs_closed = false;
cams_closed = false;
cams_visible = false;
inst_visible = false;
ctrl_visible = true;
loc_visible = false;
pwr_visible = false;
for (i = 0; i < CAMS_MAX; i++)
{
cams_list[i] = -1;
}
ClearDockingPorts();
ClearLadders();
ClearPassengerSeats();
for (i = 0; i < CONTROL_VEHICLEMAX; i++)
{
script_Path[i] = "";
ctrl_types[i] = "";
ctrlbase_parts[i] = -1;
}
for (i = 0; i < VEHICLE_MAXJOINTS; i++)
{
joints_angles[i] = ZeroVec;
joints_limits_lo[i] = ZeroVec;
joints_limits_hi[i] = ZeroVec;
joints_isLODed[i] = false;
joints_type[i] = -1;
joints_part1[i] = -1;
joints_part2[i] = -1;
joints_Astress[i] = -1;
joints_Lstress[i] = -1;
joints_FXIndex[i] = -1;
joints_breakPtcSnd[i] = "";
joints_pwrdrain[i] = 0;
joints_noDelete[i] = false;
}
for (i = 0; i < VEHICLE_MAXBLOCKS; i++)
{
blocks_part1[i] = -1;
blocks_part2[i] = -1;
blocks_noDelete[i] = false;
}
for (i = 0; i < INVENTORY_PEROBJECT_MAX; i++)
{
inventories[i] = NULL;
inventories_partNum[i] = -1;
}
for (i = 0; i < VEHICLE_MAXPARTS; i++)
{
parts_pwrdrain[i] = 0;
parts_damage[i] = -1;
parts_tough[i] = 0;
parts_mass[i] = -1;
parts_models[i] = "";
parts_types[i] = "";
parts_subtypes[i] = "";
parts_title[i] = "";
parts_pos[i] = ZeroVec;
parts_ang[i] = ZeroVec;
parts_wmat0[i] = ZeroVec;
parts_wmat1[i] = ZeroVec;
parts_wmat2[i] = ZeroVec;
parts_wmat3[i] = ZeroVec;
parts_velLin[i] = ZeroVec;
parts_velAng[i] = ZeroVec;
parts_genVec[i] = ZeroVec;
parts_genVec2[i] = ZeroVec;
parts_genVec3[i] = ZeroVec;
parts_genVec4[i] = ZeroVec;
parts_genVec5[i] = ZeroVec;
parts_genVec6[i] = ZeroVec;
parts_conPtcSnd[i] = "";
parts_storedParent[i] = -2;
statcons_part1[i] = -1;
statcons_part2[i] = -1;
inst_analyze_physMat[i] = -1;
inst_analyze_specMat[i] = "";
}
joints_num = 0;
blocks_num = 0;
ctrl_num = 0;
script_num = 0;
ctrlbase_num = 0;
parts_num = 0;
statcons_num = 0;
inventoriesNum = 0;
Agency_MisCost = 0;
DayZero_Year = 0;
DayZero_Month = 0;
DayZero_Day = 0;
DayZero_Hour = 0;
DayZero_Minute = 0;
DayZero_Second = 0;
ClearLogEntries();
ClearCurrentCommand();
ClearPacketCommands();
ClearCommands();
CommandsShowHelp = false;
}
//----------------------------------------------------------
void VehicleObject::CopyDataFromDefinition(VehicleDef def)
{
if (def)
{
defFile = def.filePath;
mapIcon = def.skeleton.instrument.mapIcon;
guiIcon = def.skeleton.instrument.guiIcon;
previewImage = def.skeleton.instrument.previewImage;
for (int i = 0; i < VEHICLE_MAXPARTS; i++)
{
InstrumentDef instrument = NULL;
if (parts_types[i] == "Instrument" || parts_types[i] == "InstrumentPassive" || parts_types[i] == "Camera" || parts_types[i] == "CameraBW" || parts_types[i] == "Antenna" || parts_types[i] == "Power" || parts_types[i] == "Turret")
instrument = g_Defs.FindInstrumentDefByTypeAndSubtype(parts_types[i], parts_subtypes[i]);
string title = "";
if (instrument)
title = instrument.name;
parts_detailsTitle[i] = title;
parts_detailsStatus[i] = "OK";
}
}
}
//----------------------------------------------------------
bool VehicleObject::CanCompleteMission(ScienceTarget stMission, Location missionLocation)
{
float comp_maj = stMission.GetMissionCompletion(ST_P_MAJOR);
bool canComp_maj = stMission.GetValidInstruments(parts_types, parts_subtypes, parts_num, true, ST_P_MAJOR, false);
bool canComp_anyAtAll = stMission.GetValidInstruments(parts_types, parts_subtypes, parts_num, true, -1, true);
// If the vehicle has a mission and its primary targets are incomplete, do not allow reassigning
/*if (mission) {
float misComp = mission.GetMissionCompletion(ST_P_MAJOR);
if (misComp >= 0 && misComp < 1)
return false;
}*/
// Check if the vehicle has the correct instruments to fulfill the primary targets
if (comp_maj >= 0 && comp_maj < 1 && !canComp_maj)
return false;
// Cannot complete any STs at all
if (!canComp_anyAtAll)
return false;
// Do not show if the vehicle is immobile and the mission requires a mobile vehicle
if (stMission.mission_mobilityRequired && !isMobile)
return false;
// Do not show if the vehicle is not designed for space and the location is a space environment
if (missionLocation && missionLocation.IsSpaceLocation() && !isSpace)
return false;
// Do not show if the vehicle is not designed for ground and the location is a ground environment
if (missionLocation && missionLocation.IsGroundLocation() && !isGround)
return false;
return true;
}
//----------------------------------------------------------
void VehicleObject::DockToPort(int otherID, int tgtPort, int myPort)
{
VehicleObject tgtVeh = owner.FindVehicleByStoreID(otherID);
//Object_BuildingBlock tgtBBlock = GetBuildingBlockByID(otherID);
if (tgtVeh)
{
if (tgtVeh.GetDocked(tgtPort))
return;
tgtVeh.dockPort_currentUndockTime[tgtPort] = 0;
tgtVeh.dockPort_dockedID[tgtPort] = Store_ID;
tgtVeh.dockPort_portIndex[tgtPort] = myPort;
dockPort_currentUndockTime[myPort] = 0;
dockPort_dockedID[myPort] = tgtVeh.Store_ID;
dockPort_portIndex[myPort] = tgtPort;
}
}
//----------------------------------------------------------
void VehicleObject::UndockPort(local int myPort, bool applyUndockForce)
{
local int dockedID = dockPort_dockedID[myPort];
local VehicleObject dockedVeh = NULL;
//local Object_BuildingBlock dockedBBlock = NULL;
if (dockedID > 0)
{
dockedVeh = owner.FindVehicleByStoreID(dockedID);
//dockedBBlock = GetBuildingBlockByID(dockedID);
}
local int dockedPort = dockPort_portIndex[myPort];
if (applyUndockForce)
dockPort_currentUndockTime[myPort] = dockPort_undockTime[myPort];
else
dockPort_currentUndockTime[myPort] = 0;
dockPort_dockedID[myPort] = -1;
dockPort_portIndex[myPort] = -1;
if (dockedVeh && dockedPort >= 0)
dockedVeh.UndockPort(dockedPort, applyUndockForce);
}
//----------------------------------------------------------
void ScanResult::AddCommand(string cmdWStr, int cmdType, string cmdValStr)
{
if (commandsCount < MAX_SCANS_CMDS) {
commandsList_widget[commandsCount] = cmdWStr;
commandsList_type[commandsCount] = cmdType;
commandsList_value[commandsCount] = cmdValStr;
commandsCount++;
}
}
//----------------------------------------------------------
widget ScanResult::LoadToWidget(widget tgtWidget)
{
if (layoutFile == "" || !tgtWidget)
return NULL;
widget wRoot = CreateWidgets(layoutFile, tgtWidget);
if (!wRoot)
return NULL;
else {
for(int n = 0; n < commandsCount; n++)
{
string wName = commandsList_widget[n];
if (wName != "") {
widget cmdWidget = FindAnyWidget(wRoot, wName);
if (cmdWidget) {
string tokens[6] = { "", "", "", "", "", "" };
int numTokens = 0;
if (commandsList_type[n] == SCAN_CMD_VISIBLE) {
if (commandsList_value[n] == "true") ShowWidget(cmdWidget, true);
else ShowWidget(cmdWidget, false);
}
if (commandsList_type[n] == SCAN_CMD_COLOR) {
numTokens = ParseString(commandsList_value[n], tokens);
if (numTokens > 0) SetWidgetColor(cmdWidget, ARGBF(atof(tokens[3]), atof(tokens[0]), atof(tokens[1]), atof(tokens[2])));
}
if (commandsList_type[n] == SCAN_CMD_TEXT)
SetWidgetTextEx(cmdWidget, 0, 3, commandsList_value[n]);
}
}
}
}
return wRoot;
}
//----------------------------------------------------------
bool VehicleObject::AddScan(ScanResult scan)
{
if(!CanAddScan())
return false;
scan.viewed = false;
scans[scansCount] = scan;
scansCount++;
return true;
}
//----------------------------------------------------------
bool VehicleObject::CanAddScan()
{
if(scansCount >= MAX_SCANS_PER_VEHICLE)
return false;
return true;
}
//----------------------------------------------------------
ScanResult VehicleObject::AddNewScan(string scanName)
{
if( FindScan(scanName) )
return NULL;
ScanResult newScan = new ScanResult();
newScan.name = scanName;
AddScan(newScan);
return newScan;
}
//----------------------------------------------------------
ScanResult VehicleObject::FindScan(string name)
{
for(int n = 0; n < scansCount; n++)
{
ScanResult scan = scans[n];
if(scan.name == name)
return scan;
}
return NULL;
}
//----------------------------------------------------------
void VehicleObject::DestroyScans()
{
for(int n = 0; n < scansCount; n++)
{
ScanResult scan = scans[n];
delete scan;
}
scansCount = 0;
}
//----------------------------------------------------------
bool VehicleObject::AddPhoto(Photo photo)
{
//destroy oldest photo if canot store new one
if(photosCount == MAX_PHOTOS_PER_VEHICLE)
{
Photo oldestPhoto = photos[0];
DestroyPhoto(oldestPhoto, true);
}
photos[photosCount] = photo;
photosCount++;
return true;
}
//----------------------------------------------------------
void VehicleObject::DestroyLogoutPhoto(bool destroyFile)
{
if(logoutPhoto)
{
if(destroyFile)
DestroyPhotoFile(logoutPhoto.filePath); //destroy photo file (if possible)
delete logoutPhoto;
logoutPhoto = NULL;
}
}
//----------------------------------------------------------
void VehicleObject::DestroyPhotoFile(string filePath)
{
//remove file from game dependencies list
g_Game.RemoveFileDependence( filePath );
if( g_Game.AnySaveDependsOnFile( filePath ) )
return; //any save game depends on this file. cannot delete!!!
if( !FileExist( filePath ) )
return; //file is missing. nothing to delete
DeleteFile( filePath );
}
//----------------------------------------------------------
Photo VehicleObject::CreateScreenshotPhoto(string photoName, int photoWidth, int photoHeight)
{
RenderTargetWidget renderWidget = (RenderTargetWidget)FindWidget(NULL, "Root.RootPhoto");
if(!renderWidget || noPhotos)
return NULL; //nothing to capture
//get photos folder. create if not exist
string photosDir = g_Game.GetPhotosDir(true);
if(photosDir == "")
return NULL; //anything wrong. cannot create photos directory
Photo photo = new Photo();
GetHourMinuteSecond(photo.hour, photo.minute, photo.second);
GetYearMonthDay(photo.year, photo.month, photo.day);
//add unique postfix
photoName += "_" + itoal(photo.year, 4) + "-" + itoal(photo.month, 2) + "-" + itoal(photo.day, 2) + "_" + itoal(photo.hour, 2) + "-" + itoal(photo.minute, 2) + "-" + itoal(photo.second, 2);
string filePath = photosDir + "/" + photoName + ".jpg";
if( FileExist( filePath ) )
DeleteFile( filePath ); //any wrong file. delete it to possible write new one
photo.name = photoName;
photo.filePath = filePath;
photo.mission = mission;
photo.location = owner;
if( !g_Game.MakeScreenshotToFile(renderWidget, photoWidth, photoHeight, photo.filePath, FILEFORMAT_JPEG) )
{
delete photo;
return NULL;
}
g_Game.AddFileDependence( photo.filePath );
//make preview photo for steam (16:9 and with must be 200)
int previewPhotoWidth = 200;
int previewPhotoHeight = 200;
// float previewPhotoHeight = (float)previewPhotoWidth * 0.5625;
string previewFilePath = photo.GetPreviewFilePath();
if( g_Game.MakeScreenshotToFile(renderWidget, previewPhotoWidth, previewPhotoHeight, previewFilePath, FILEFORMAT_JPEG) )
g_Game.AddFileDependence( previewFilePath );
return photo;
}
//----------------------------------------------------------
Photo VehicleObject::AddScreenshotPhoto(int camNum)
{
// Assemble unique photo name
string photoName = name + "_photo" + itoa(photosCount + 1);
while( FindPhoto(photoName) )
{
photosCount++;
photoName = name + "_photo" + itoa(photosCount + 1);
}
RenderTargetWidget renderWidget = (RenderTargetWidget)FindWidget(NULL, "Root.RootPhoto");
if (renderWidget) {
renderWidget.Show(true);
SetWidgetWorld(renderWidget, g_Game.CurrentWorld, camNum);
}
Photo photo = CreateScreenshotPhoto(photoName, PHOTO_IMAGE_WIDTH, PHOTO_IMAGE_HEIGHT);
if (renderWidget)
renderWidget.Show(false);
if(photo)
AddPhoto(photo);
return photo;
}
//----------------------------------------------------------
Photo VehicleObject::MakeLogoutPhoto()
{
Print("Logout photo !!!!!!!!!!!")
DestroyLogoutPhoto(true);
RenderTargetWidget renderWidget = (RenderTargetWidget)FindWidget(NULL, "Root.RootPhoto");
if (renderWidget && CurrentListenCam >= 0) {
renderWidget.Show(true);
SetWidgetWorld(renderWidget, g_Game.CurrentWorld, CurrentListenCam);
}
logoutPhoto = CreateScreenshotPhoto(name + "_logout", PHOTO_LOGOUTIMAGE_WIDTH, PHOTO_LOGOUTIMAGE_HEIGHT);
if (renderWidget)
renderWidget.Show(false);
return logoutPhoto;
}
//----------------------------------------------------------
Photo VehicleObject::FindPhoto(string name)
{
for(int n = 0; n < photosCount; n++)
{
Photo photo = photos[n];
if(photo.name == name)
return photo;
}
return NULL;
}
//----------------------------------------------------------
int VehicleObject::GetPhotoIndex(Photo photo)
{
for(int n = 0; n < photosCount; n++)
{
Photo p = photos[n];
if(p == photo)
return n;
}
return -1;
}
//----------------------------------------------------------
int VehicleObject::GetValidPhotosCount()
{
int count = 0;
for(int n = 0; n < photosCount; n++)
{
Photo photo = photos[n];
if( !FileExist( photo.filePath ) )
continue;
count++;
}
return count;
}
//----------------------------------------------------------
void VehicleObject::DestroyPhotos(bool destroyFiles)
{
for(int n = 0; n < photosCount; n++)
{
Photo photo = photos[n];
if(destroyFiles)
{
DestroyPhotoFile(photo.filePath); //destroy photo file (if possible)
DestroyPhotoFile( photo.GetPreviewFilePath() );
}
delete photo;
}
photosCount = 0;
}
//----------------------------------------------------------
void VehicleObject::DestroyPhoto(Photo photo, bool destroyFile)
{
int index = GetPhotoIndex(photo);
if(index == -1)
return;
int lastIndex = photosCount - 1;
for(int n = index; n < lastIndex; n++)
photos[n] = photos[n + 1];
photosCount--;
if(destroyFile)
{
DestroyPhotoFile(photo.filePath); //destroy photo file (if possible)
DestroyPhotoFile( photo.GetPreviewFilePath() );
}
delete photo;
}
//----------------------------------------------------------
void VehicleObject::ClearLogEntries()
{
for(int n = 0; n < MAX_VEHICLES_LOG_ENTRIES; n++)
{
LogEntries[n] = "";
LogDate[n] = "";
}
LogEntry_Cur = 0;
}
//----------------------------------------------------------
void VehicleObject::AddLogEntry(string logEntry)
{
int year, month, day, hour, minute, second;
GetYearMonthDay(year, month, day);
GetHourMinuteSecond(hour, minute, second);
string date = itoa(day);
if (day < 10)
date = "0" + date;
date += " " + "#tkom_month_" + itoa(month);
date += " " + itoa(year);
LogDate[LogEntry_Cur] = String(TimeToString(Vector(hour, minute, second)) + " - " + date);
LogEntries[LogEntry_Cur] = String(logEntry);
LogEntry_Cur++;
if (LogEntry_Cur >= MAX_VEHICLES_LOG_ENTRIES)
LogEntry_Cur = 0;
}
//----------------------------------------------------------
void VehicleObject::ClearCurrentCommand()
{
for(int n = 0; n < MAX_VEHICLES_COMMAND_PARTS; n++)
{
CurrentCommandParsed[n] = "";
}
CurrentCommand = "";
CurrentCommandParsed_Num = 0;
CurrentCommandValidParts = 0;
CurrentCommandRequiredParts = 0;
CurrentCommandRequiredPoint = false;
}
//----------------------------------------------------------
void VehicleObject::SetCurrentCommand(string command)
{
ClearCurrentCommand();
if (command != "") {
string CurrentCommandParsedTmp[MAX_VEHICLES_COMMAND_PARSEPARTS];
int CurrentCommandParsed_NumTmp;
CurrentCommandParsed_NumTmp = ParseString(command, CurrentCommandParsedTmp);
int n = 0;
int n2 = 0;
while (n < CurrentCommandParsed_NumTmp)
{
int nNext = n + 1;
CurrentCommandParsed[n2] = CurrentCommandParsed[n2] + CurrentCommandParsedTmp[n];
if (nNext < CurrentCommandParsed_NumTmp && CurrentCommandParsedTmp[n] != "-" && CurrentCommandParsedTmp[nNext] != "-") // Current or next string is not joiner, so increment
n2++;
n++;
}
CurrentCommandParsed_Num = n2;
CurrentCommand = command;
}
}
//----------------------------------------------------------
void VehicleObject::ClearPacketCommands()
{
for(int n = 0; n < MAX_VEHICLES_COMMANDS_PACKET; n++)
{
PacketCommands[n] = "";
PacketCommands_CustomPos[n] = ZeroVec;
PacketCommands_CustomDir[n] = ZeroVec;
}
PacketCommands_Cur = 0;
}
//----------------------------------------------------------
void VehicleObject::AddPacketCommand(string command, vector commandPos, vector commandDir)
{
if (PacketCommands_Cur >= MAX_VEHICLES_COMMANDS_PACKET || command == "")
return;
PacketCommands[PacketCommands_Cur] = command;
PacketCommands_CustomPos[PacketCommands_Cur] = commandPos;
PacketCommands_CustomDir[PacketCommands_Cur] = commandDir;
PacketCommands_Cur++;
}
//----------------------------------------------------------
void VehicleObject::ClearCommands()
{
ClearExecuteCommand();
for(int n = 0; n < MAX_VEHICLES_COMMANDS; n++)
{
Commands[n] = "";
CommandsDate[n] = "";
Commands_CustomPos[n] = ZeroVec;
Commands_CustomDir[n] = ZeroVec;
}
Commands_Cur = 0;
CommandPerforming_Pct = 0;
CommandPerforming_WaitTime = 0;
}
//----------------------------------------------------------
void VehicleObject::AddCommand(string command, vector commandPos, vector commandDir)
{
if (Commands_Cur >= MAX_VEHICLES_COMMANDS || command == "")
return;
int year, month, day, hour, minute, second;
if (g_Campaign.Rover_RealUTC) {
GetYearMonthDay(year, month, day);
GetHourMinuteSecond(hour, minute, second);
} else {
year = g_Campaign.SimUTC_year;
month = g_Campaign.SimUTC_month;
day = g_Campaign.SimUTC_day;
hour = g_Campaign.SimUTC_hour;
minute = g_Campaign.SimUTC_minute;
second = g_Campaign.SimUTC_second;
}
Commands[Commands_Cur] = command;
Commands_CustomPos[Commands_Cur] = commandPos;
Commands_CustomDir[Commands_Cur] = commandDir;
CommandsDate[Commands_Cur] = itoa(year) + " " + itoa(month) + " " + itoa(day) + " " + itoa(hour) + " " + itoa(minute) + " " + itoa(second) + " ";
Commands_Cur++;
}
//----------------------------------------------------------
void VehicleObject::RemoveCommand(int index)
{
for(int n = index; n < Commands_Cur; n++)
{
if (sum(n + 1) == Commands_Cur) {
Commands[n] = "";
CommandsDate[n] = "";
Commands_CustomPos[n] = ZeroVec;
Commands_CustomDir[n] = ZeroVec;
} else {
Commands[n] = Commands[n + 1];
CommandsDate[n] = CommandsDate[n + 1];
Commands_CustomPos[n] = Commands_CustomPos[n + 1];
Commands_CustomDir[n] = Commands_CustomDir[n + 1];
}
}
Commands_Cur--;
}
//----------------------------------------------------------
void VehicleObject::CommandComplete(bool successful)
{
if (Commands_Cur <= 0)
return;
if (successful)
AddLogEntry("#tkom_log_cmdcomp " + Commands[ExecuteCommandParsed_Index]);
else
AddLogEntry("#tkom_log_cmdfail " + Commands[ExecuteCommandParsed_Index]);
RemoveCommand(ExecuteCommandParsed_Index);
ClearExecuteCommand();
if (Commands_Cur <= 0)
AddLogEntry("#tkom_log_cmdseq_end");
}
//----------------------------------------------------------
void VehicleObject::CopyPacketCommandsToCommands()
{
for(local int n = 0; n < PacketCommands_Cur; n++)
{
AddCommand(PacketCommands[n], PacketCommands_CustomPos[n], PacketCommands_CustomDir[n]);
}
ClearPacketCommands();
}
//----------------------------------------------------------
void VehicleObject::ClearExecuteCommand()
{
for(int n = 0; n < MAX_VEHICLES_COMMAND_PARTS; n++)
{
ExecuteCommandParsed[n] = "";
}
ExecuteCommandParsed_Num = 0;
ExecuteCommandParsed_Index = -1;
CommandPerforming_Pct = 0;
CommandPerforming_WaitTime = 0;
}
//----------------------------------------------------------
void VehicleObject::SetExecuteCommand(int index)
{
ClearExecuteCommand();
if (Commands[index] != "") {
ExecuteCommandParsed_Index = index;
CommandPerforming_WaitTime = MAX_VEHICLES_COMMAND_WAITTIME;
string ExecuteCommandParsedTmp[MAX_VEHICLES_COMMAND_PARSEPARTS];
int ExecuteCommandParsed_NumTmp;
ExecuteCommandParsed_NumTmp = ParseString(Commands[index], ExecuteCommandParsedTmp);
int n = 0;
int n2 = 0;
while (n < ExecuteCommandParsed_NumTmp)
{
int nNext = n + 1;
ExecuteCommandParsed[n2] = ExecuteCommandParsed[n2] + ExecuteCommandParsedTmp[n];
if (nNext < ExecuteCommandParsed_NumTmp && ExecuteCommandParsedTmp[n] != "-" && ExecuteCommandParsedTmp[nNext] != "-") // Current or next string is not joiner, so increment
n2++;
n++;
}
ExecuteCommandParsed_Num = n2;
if (ExecuteCommandParsed[0] == "WAIT") {
int year, month, day, hour, minute, second, millisecond;
if (g_Campaign.Rover_RealUTC) {
GetYearMonthDay(year, month, day);
GetHourMinuteSecond(hour, minute, second);
millisecond = 0;
} else {
year = g_Campaign.SimUTC_year;
month = g_Campaign.SimUTC_month;
day = g_Campaign.SimUTC_day;
hour = g_Campaign.SimUTC_hour;
minute = g_Campaign.SimUTC_minute;
second = g_Campaign.SimUTC_second;
millisecond = g_Campaign.SimUTC_millisecond;
}
WaitCommand_DateStorage[0] = year;
WaitCommand_DateStorage[1] = month;
WaitCommand_DateStorage[2] = day;
WaitCommand_DateStorage[3] = hour;
WaitCommand_DateStorage[4] = minute;
WaitCommand_DateStorage[5] = second;
WaitCommand_DateStorage[6] = millisecond;
}
}
}
//----------------------------------------------------------
bool VehicleObject::IsCommandWithinDate(int index, int year, int month, int day, int hour, int minute, int second)
{
int cmd_year, cmd_month, cmd_day, cmd_hour, cmd_minute, cmd_second;
int date[6];
GetCommandDate(index, date);
cmd_year = date[0];
cmd_month = date[1];
cmd_day = date[2];
cmd_hour = date[3];
cmd_minute = date[4];
cmd_second = date[5];
// Add OWLT here
if (cmd_year > year) return false;
if (cmd_month > month && cmd_year == year) return false;
if (cmd_day > day && cmd_month == month && cmd_year == year) return false;
if (cmd_hour > hour && cmd_day == day && cmd_month == month && cmd_year == year) return false;
if (cmd_minute > minute && cmd_hour == hour && cmd_day == day && cmd_month == month && cmd_year == year) return false;
if (cmd_second > second && cmd_minute == minute && cmd_hour == hour && cmd_day == day && cmd_month == month && cmd_year == year) return false;
return true;
}
//----------------------------------------------------------
void VehicleObject::GetCommandDate(int index, int date[6])
{
int cmd_year, cmd_month, cmd_day, cmd_hour, cmd_minute, cmd_second;
string cmdDate = CommandsDate[index];
string cmdDateParsed[6];
int numTokens = ParseString(cmdDate, cmdDateParsed);
for (int i = 0; i < numTokens; i++) {
cmd_year = atoi(cmdDateParsed[0]);
cmd_month = atoi(cmdDateParsed[1]);
cmd_day = atoi(cmdDateParsed[2]);
cmd_hour = atoi(cmdDateParsed[3]);
cmd_minute = atoi(cmdDateParsed[4]);
cmd_second = atoi(cmdDateParsed[5]);
}
date[0] = cmd_year;
date[1] = cmd_month;
date[2] = cmd_day;
date[3] = cmd_hour;
date[4] = cmd_minute;
date[5] = cmd_second;
}
//----------------------------------------------------------
void VehicleObject::UpdateCommandSequence(float timeSlice)
{
CommandPerforming_WaitTime -= timeSlice;
clamp CommandPerforming_WaitTime<0, MAX_VEHICLES_COMMAND_WAITTIME>;
int year, month, day, hour, minute, second, millisecond;
start:
if (g_Campaign.Rover_RealUTC) {
GetYearMonthDay(year, month, day);
GetHourMinuteSecond(hour, minute, second);
millisecond = UTC_LastMS;
} else {
year = g_Campaign.SimUTC_year;
month = g_Campaign.SimUTC_month;
day = g_Campaign.SimUTC_day;
hour = g_Campaign.SimUTC_hour;
minute = g_Campaign.SimUTC_minute;
second = g_Campaign.SimUTC_second;
millisecond = g_Campaign.SimUTC_millisecond;
}
if (Commands_Cur > 0) {
// Sort through commands, execute if within date
for(local int i = 0; i < Commands_Cur; i++)
{
if (IsCommandWithinDate(i, year, month, day, hour, minute, second)) {
if (Commands[i] == "CLEAR") { // Found CLEAR command, so clear commands prior to this one
int date[6];
GetCommandDate(i, date);
year = date[0];
month = date[1];
day = date[2];
hour = date[3];
minute = date[4];
second = date[5];
remove:
for(local int n = 0; n < i; n++)
{
if (IsCommandWithinDate(n, year, month, day, hour, minute, second)) {
RemoveCommand(n);
i--;
goto remove;
}
}
RemoveCommand(i);
ClearExecuteCommand();
goto start;
}
if (ExecuteCommandParsed_Index == -1)
SetExecuteCommand(i);
}
}
if (ExecuteCommandParsed_Num > 0 && ExecuteCommandParsed[0] == "WAIT") { // Performing WAIT command, so count down time
float waitTime = atof(ExecuteCommandParsed[1]);
string timeType = ExecuteCommandParsed[2];
vector JDVec = GetJulianDate(year, month, day, hour, minute, second, 0);
float JDNoMS = JDVec[1];
float JDMS = JDVec[2];
JDVec = GetJulianDate(WaitCommand_DateStorage[0], WaitCommand_DateStorage[1], WaitCommand_DateStorage[2], WaitCommand_DateStorage[3], WaitCommand_DateStorage[4], WaitCommand_DateStorage[5], WaitCommand_DateStorage[6]);
float WaitJDNoMS = JDVec[1];
float WaitJDMS = JDVec[2];
float diff_JD = fsum(JDNoMS - WaitJDNoMS) + fsum(JDMS - WaitJDMS);
if (diff_JD < 0) {
WaitCommand_DateStorage[0] = year;
WaitCommand_DateStorage[1] = month;
WaitCommand_DateStorage[2] = day;
WaitCommand_DateStorage[3] = hour;
WaitCommand_DateStorage[4] = minute;
WaitCommand_DateStorage[5] = second;
WaitCommand_DateStorage[6] = millisecond;
} else {
float hours = diff_JD * 24;
float minutes = hours * 60;
float seconds = minutes * 60;
if (timeType == "H") CommandPerforming_Pct = hours / waitTime;
if (timeType == "M") CommandPerforming_Pct = minutes / waitTime;
if (timeType == "S") CommandPerforming_Pct = seconds / waitTime;
if (CommandPerforming_Pct >= 1) CommandComplete(true);
}
}
}
}
//----------------------------------------------------------
bool VehicleObject::GetIsLocallyControlled()
{
if (!vehicleHandler)
return false;
return vehicleHandler.IsControlledByLocalPlayer();
}
//----------------------------------------------------------
void VehicleObject::SetDayZero()
{
if (g_Campaign.Rover_RealUTC) {
GetYearMonthDayUTC(DayZero_Year, DayZero_Month, DayZero_Day);
GetHourMinuteSecondUTC(DayZero_Hour, DayZero_Minute, DayZero_Second);
} else {
DayZero_Year = g_Campaign.SimUTC_year;
DayZero_Month = g_Campaign.SimUTC_month;
DayZero_Day = g_Campaign.SimUTC_day;
DayZero_Hour = g_Campaign.SimUTC_hour;
DayZero_Minute = g_Campaign.SimUTC_minute;
DayZero_Second = g_Campaign.SimUTC_second;
}
}
//----------------------------------------------------------
float VehicleObject::GetMissionDayCount()
{
int year, month, day, hour, minute, second;
if (g_Campaign.Rover_RealUTC) {
GetYearMonthDayUTC(year, month, day);
GetHourMinuteSecondUTC(hour, minute, second);
} else {
year = g_Campaign.SimUTC_year;
month = g_Campaign.SimUTC_month;
day = g_Campaign.SimUTC_day;
hour = g_Campaign.SimUTC_hour;
minute = g_Campaign.SimUTC_minute;
second = g_Campaign.SimUTC_second;
}
return GetDayCount(DayZero_Year, DayZero_Month, DayZero_Day, DayZero_Hour, DayZero_Minute, DayZero_Second, year, month, day, hour, minute, second, 1.027491252);
}
//----------------------------------------------------------
string VehicleObject::GenerateCampaignName()
{
if (!g_Campaign)
return "";
name = g_Campaign.GenerateVehicleName();
return name;
}
//----------------------------------------------------------
void CharacterObject::BoardBBlockSeat(int seatIndex, _entity bblockBase)
{
Object_BuildingBlock bblock = (Object_BuildingBlock)bblockBase;
if (bblock.Seats_CharacterID[seatIndex] <= 0)
{
bblock.SetSeatCharacterByID(seatIndex, Store_ID);
inBlockID = bblock.GetID();
inBlockSeat = seatIndex;
}
}
//----------------------------------------------------------
void CharacterObject::DisembarkBBlock()
{
if (inBlockID > 0)
{
Object_BuildingBlock bblock = GetBBlockByID(inBlockID);
if (bblock && inBlockSeat != -1)
bblock.SetSeatCharacterByID(inBlockSeat, 0);
inBlockID = 0;
inBlockSeat = -1;
}
}
//----------------------------------------------------------
bool CharacterObject::CanSleepInSeat()
{
if (inVehicle && inVehicleSeat != -1 && inVehicle.passengerSeat_canSleep[inVehicleSeat])
return true;
if (inBlockID > 0 && inBlockSeat != -1)
{
Object_BuildingBlock inbblock = GetBBlockByID(inBlockID);
if (inbblock && inbblock.Seats_CanSleep[inBlockSeat])
return true;
}
return false;
}
//----------------------------------------------------------
void CharacterObject::EnterBBlockSeat(_entity bblockBase, int reachSeat)
{
Object_BuildingBlock bblock = (Object_BuildingBlock)bblockBase;
HoldObjectID = 0;
HoldObjectSubID = 0;
TraceObjectID = 0;
TraceObjectSubID = 0;
BoardBBlockSeat(reachSeat, bblock);
CursorInfoType = CHAR_CURSORINFO_NULL;
MovementState = CHAR_MOVESTATE_SEATED;
}
//----------------------------------------------------------
string CharacterObject::GenerateCampaignName()
{
if (!g_Campaign)
return "";
name = g_Campaign.GenerateCharacterName();
return name;
}
//----------------------------------------------------------
void RagdollObject::FillData_GenVars(float genFloats[], int genInts[], vector genVecs[], string genStrings[])
{
for (int i = 0; i < RAGDOLL_GENVARS; i++)
{
GenFloats[i] = genFloats[i];
GenInts[i] = genInts[i];
GenVecs[i] = genVecs[i];
GenStrings[i] = genStrings[i];
}
}
//----------------------------------------------------------
void RagdollObject::FillData_Parts1(float mass[], string models[], string names[], bool statics[], bool nophys[], vector poss[], vector angs[], string ptc[])
{
for (int i = 0; i < RAGDOLL_MAXPARTS; i++)
{
parts_mass[i] = mass[i];
parts_models[i] = models[i];
parts_name[i] = names[i];
parts_static[i] = statics[i];
parts_nophys[i] = nophys[i];
parts_pos[i] = poss[i];
parts_ang[i] = angs[i];
parts_conPtcSnd[i] = ptc[i];
}
}
//----------------------------------------------------------
void RagdollObject::FillData_Parts2(vector mat0[], vector mat1[], vector mat2[], vector mat3[], vector vellin[], vector velang[])
{
for (int i = 0; i < RAGDOLL_MAXPARTS; i++)
{
parts_wmat0[i] = mat0[i];
parts_wmat1[i] = mat1[i];
parts_wmat2[i] = mat2[i];
parts_wmat3[i] = mat3[i];
parts_velLin[i] = vellin[i];
parts_velAng[i] = velang[i];
}
}
//----------------------------------------------------------
void RagdollObject::FillData_Blocks(int part1[], int part2[])
{
for (int i = 0; i < RAGDOLL_MAXBLOCKS; i++)
{
blocks_part1[i] = part1[i];
blocks_part2[i] = part2[i];
}
}
//----------------------------------------------------------
void RagdollObject::FillData_Joints(vector angles[], vector limitlo[], vector limithi[], float springstiff[], float springdamp[], int part1[], int part2[])
{
for (int i = 0; i < RAGDOLL_MAXJOINTS; i++)
{
joints_angles[i] = angles[i];
joints_limits_lo[i] = limitlo[i];
joints_limits_hi[i] = limithi[i];
joints_spring_stiff[i] = springstiff[i];
joints_spring_damp[i] = springdamp[i];
joints_part1[i] = part1[i];
joints_part2[i] = part2[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_CtrlScript(string csdata0[], string csdata1[])
{
ctrl_num = 0;
script_num = 0;
for (int i = 0; i < CONTROL_VEHICLEMAX; i++)
{
if (csdata0[i] != "") {
script_Path[script_num] = csdata0[i];
script_num++;
}
if (csdata1[i] != "") {
ctrl_types[ctrl_num] = csdata1[i];
ctrl_num++;
}
}
}
//----------------------------------------------------------
void VehicleObject::FillData_CtrlBase(int cbdata0[])
{
ctrlbase_num = 0;
for (int i = 0; i < CONTROL_VEHICLEMAX; i++)
{
ctrlbase_parts[i] = cbdata0[i];
if (cbdata0[i] > 0)
ctrlbase_num++;
}
}
//----------------------------------------------------------
void VehicleObject::FillData_DockPorts(int numPorts, int dpdata0[], vector dpdata1[], vector dpdata2[], float dpdata3[], float dpdata4[], string dpdata5[], float dpdata6[], float dpdata7[])
{
dockPort_num = numPorts;
for (int i = 0; i < MAX_DOCKPORTS; i++)
{
SetDockingPort(i, dpdata0[i], dpdata1[i], dpdata2[i], dpdata5[i], dpdata3[i], dpdata4[i], dpdata6[i], dpdata7[i]);
}
}
//----------------------------------------------------------
void VehicleObject::FillData_DockPortsDocked(int dpdata0[], int dpdata1[])
{
for (int i = 0; i < dockPort_num; i++)
{
dockPort_dockedID[i] = dpdata0[i];
dockPort_portIndex[i] = dpdata1[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Joints(vector jdata0[], vector jdata1[], vector jdata2[], int jdata3[], int jdata4[], int jdata5[], float jdata6[], float jdata7[], string jdata8[], float jdata9[], bool jdata10[], bool jdata11[])
{
for (int i = 0; i < VEHICLE_MAXJOINTS; i++)
{
joints_angles[i] = jdata0[i];
joints_limits_lo[i] = jdata1[i];
joints_limits_hi[i] = jdata2[i];
joints_isLODed[i] = jdata11[i];
joints_type[i] = jdata3[i];
joints_part1[i] = jdata4[i];
joints_part2[i] = jdata5[i];
joints_Astress[i] = jdata6[i];
joints_Lstress[i] = jdata7[i];
joints_breakPtcSnd[i] = jdata8[i];
joints_pwrdrain[i] = jdata9[i];
joints_noDelete[i] = jdata10[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Blocks(int bdata0[], int bdata1[], bool bdata2[])
{
for (int i = 0; i < VEHICLE_MAXBLOCKS; i++)
{
blocks_part1[i] = bdata0[i];
blocks_part2[i] = bdata1[i];
blocks_noDelete[i] = bdata2[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Parts(float pdata0[], int pdata1[], float pdata2[], string pdata3[], string pdata4[], string pdata5[], vector pdata6[], vector pdata7[], vector pdata8[], vector pdata9[], vector pdata10[])
{
for (int i = 0; i < VEHICLE_MAXPARTS; i++)
{
parts_damage[i] = pdata0[i];
parts_tough[i] = pdata1[i];
parts_mass[i] = pdata2[i];
parts_models[i] = pdata3[i];
parts_types[i] = pdata4[i];
parts_subtypes[i] = pdata5[i];
parts_pos[i] = pdata6[i];
parts_ang[i] = pdata7[i];
parts_wmat0[i] = pdata8[i];
parts_wmat1[i] = pdata9[i];
parts_wmat2[i] = pdata10[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Parts2(vector pdata11[], vector pdata12[], vector pdata13[], vector pdata14[], vector pdata15[], vector pdata16[], vector pdata17[], vector pdata18[], vector pdata19[], string pdata20[], int pdata21[])
{
for (int i = 0; i < VEHICLE_MAXPARTS; i++)
{
parts_wmat3[i] = pdata11[i];
parts_velLin[i] = pdata12[i];
parts_velAng[i] = pdata13[i];
parts_genVec[i] = pdata14[i];
parts_genVec2[i] = pdata15[i];
parts_genVec3[i] = pdata16[i];
parts_genVec4[i] = pdata17[i];
parts_genVec5[i] = pdata18[i];
parts_genVec6[i] = pdata19[i];
parts_conPtcSnd[i] = pdata20[i];
parts_storedParent[i] = pdata21[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Parts3(string pdata22[])
{
for (int i = 0; i < VEHICLE_MAXPARTS; i++)
{
parts_title[i] = pdata22[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Inst(int idata1[], string idata2[])
{
for (int i = 0; i < VEHICLE_MAXPARTS; i++)
{
inst_analyze_physMat[i] = idata1[i];
inst_analyze_specMat[i] = idata2[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_StatCon(int cdata0[], int cdata1[])
{
for (int i = 0; i < VEHICLE_MAXPARTS; i++)
{
statcons_part1[i] = cdata0[i];
statcons_part2[i] = cdata1[i];
}
}
//----------------------------------------------------------
void VehicleObject::FillData_Inventories(string dataInvNames[INVENTORY_PEROBJECT_MAX], int dataPartIndex[INVENTORY_PEROBJECT_MAX], string dataLayout[INVENTORY_PEROBJECT_MAX], string dataHiTxt[INVENTORY_PEROBJECT_MAX], string dataHiImg[INVENTORY_PEROBJECT_MAX], int dataSlotNum[INVENTORY_PEROBJECT_MAX], string dataSlotTypes[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX])
{
for (local int i = 0; i < INVENTORY_PEROBJECT_MAX; i++)
{
string invName = dataInvNames[i];
string invLayout = dataLayout[i];
string invHiTxt = dataHiTxt[i];
string invHiImg = dataHiImg[i];
int invPartIndex = dataPartIndex[i];
int invSlotNum = dataSlotNum[i];
if (invName == "")
continue;
if (invLayout == "")
continue;
if (invHiTxt == "")
continue;
if (invHiImg == "")
continue;
if (invPartIndex < 0)
continue;
if (invSlotNum <= 0)
continue;
string invSlotTypes[INVENTORY_SLOTS_MAX];
for (int i2 = 0; i2 < INVENTORY_SLOTS_MAX; i2++)
{
invSlotTypes[i2] = dataSlotTypes[i][i2];
}
CreateInventory(i, invName, invPartIndex, invLayout, invHiTxt, invHiImg, invSlotNum, invSlotTypes);
}
}
//----------------------------------------------------------
void VehicleObject::FillData_StoredInventoryItems(string dataItmTitles[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmDescs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmImgs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmScripts[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmCFGs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmMdls[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmRmps[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmFX[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], float dataItmMass[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmVldSlts[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], int dataItmGenInts[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], float dataItmGenFloats[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmGenVecs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX], string dataItmGenStrs[INVENTORY_PEROBJECT_MAX][INVENTORY_SLOTS_MAX])
{
for (local int i = 0; i < inventoriesNum; i++)
{
local Inventory inventory = inventories[i];
if (!inventory)
continue;
for (local int i2 = 0; i2 < inventory.slotNum; i2++)
{
int itemID = Global_GetHighestInvItemID() + 1;
string itemTitle = dataItmTitles[i][i2];
string itemDesc = dataItmDescs[i][i2];
string itemImage = dataItmImgs[i][i2];
string itemScript = dataItmScripts[i][i2];
string itemConfig = dataItmCFGs[i][i2];
string itemModel = dataItmMdls[i][i2];
string itemRemap = dataItmRmps[i][i2];
string itemFX = dataItmFX[i][i2];
float itemMass = dataItmMass[i][i2];
string itemValidSlots = dataItmVldSlts[i][i2];
int itemGenInt = dataItmGenInts[i][i2];
float itemGenFloat = dataItmGenFloats[i][i2];
vector itemGenVec = String2Vector(dataItmGenVecs[i][i2]);
string itemGenStr = dataItmGenStrs[i][i2];
if (itemTitle == "")
continue;
if (itemImage == "")
continue;
if (itemConfig == "")
continue;
if (itemModel == "")
continue;
inventory.SpawnStoredItemObject(itemID, i2, itemTitle, itemDesc, itemImage, itemScript, itemConfig, itemModel, itemRemap, itemFX, itemMass, itemValidSlots, itemGenInt, itemGenFloat, itemGenVec, itemGenStr);
}
}
}
//----------------------------------------------------------
void VehicleObject::FillData_GenString(string strdata[])
{
for (local int i = 0; i < MAX_VEHICLES_GENSTRINGNUM; i++)
{
GenStrings[i] = strdata[i];
}
}
#include "scripts/Campaign/GeneratedMission.h"
//----------------------------------------------------------
bool Resource_Base::IsDiscoveredInSector(int sectorX, int sectorY)
{
switch(areaType)
{
case RESOURCE_AREATYPE_GROUND:
{
return owner.ResourceDiscovered_Ground[sectorX][sectorY];
}
case RESOURCE_AREATYPE_SURFACE:
{
return owner.ResourceDiscovered_Surface[sectorX][sectorY];
}
case RESOURCE_AREATYPE_ATMOSPHERIC:
{
return owner.ResourceDiscovered_Atmospheric[sectorX][sectorY];
}
}
}
//----------------------------------------------------------
void Resource_Base::DistributeResource()
{
ClearResource();
if (distrib_SectorNumX == 0 || distrib_SectorNumY == 0)
{
Print(String("DISTRIBUTERESOURCE: Could not distribute resource '" + name + "', sector count is zero!!!"));
return;
}
randomize(distributeSeed); // Set randomizer seed to stored distribution seed
float expDistribClumping = sin(distrib_Clumping * 90 * DEG2RAD);
float inv_expDistribClumping = 1 - expDistribClumping;
int resourceToDistribute_phase1 = floor(1 - expDistribClumping * distrib_MaxAmountTotal);
int resourceToDistribute_phase2 = distrib_MaxAmountTotal - resourceToDistribute_phase1;
int resourceToDistribute;
int x, y, amt, rndX, rndY, maxPerSector;
// Phase 1 - distribute per sector
if (resourceToDistribute_phase1 > 0)
{
resourceToDistribute = resourceToDistribute_phase1;
maxPerSector = floor(resourceToDistribute / sum(distrib_SectorNumX * distrib_SectorNumY));
if (maxPerSector > 0)
{
for (x = 0; x < distrib_SectorNumX; x++)
{
for (y = 0; y < distrib_SectorNumY; y++)
{
amt = floor(frand(0.9, 1.1) * maxPerSector);
if (frand(0, 1) < 0.25)
clamp amt<5, resourceToDistribute>;
else
clamp amt<0, resourceToDistribute>;
SetAmountInSector(amt, x, y);
Changed[x][y] = false;
resourceToDistribute -= amt;
if (resourceToDistribute <= 0)
break;
}
if (resourceToDistribute <= 0)
break;
}
while(resourceToDistribute > 0)
{
rndX = rand(0, distrib_SectorNumX);
rndY = rand(0, distrib_SectorNumY);
amt = floor(frand(0.1, 0.4) * maxPerSector);
if (frand(0, 1) < 0.25)
clamp amt<5, resourceToDistribute>;
else
clamp amt<0, resourceToDistribute>;
AddAmountToSector(amt, rndX, rndY);
Changed[rndX][rndY] = false;
resourceToDistribute -= amt;
}
}
}
// Phase 2 - distribute 'clumps' of resource
if (resourceToDistribute_phase2 > 0)
{
resourceToDistribute = resourceToDistribute_phase2;
while(resourceToDistribute > 0)
{
float spreadFactor = frand(inv_expDistribClumping + 1, inv_expDistribClumping * 3 + 2);
float amountFactor = frand(expDistribClumping * 50 + 50, expDistribClumping * 100 + 100);
maxPerSector = floor(resourceToDistribute_phase2 / fsum(distrib_SectorNumX * distrib_SectorNumY) * amountFactor);
clamp maxPerSector<10, resourceToDistribute>;
rndX = rand(0, distrib_SectorNumX);
rndY = rand(0, distrib_SectorNumY);
vector clumpPos = Vector(fsum(rndX), fsum(rndY), 0);
int clumpSectorSpread = floor(spreadFactor * 10 * frand(0.6, 1.4));
if (clumpSectorSpread < 3)
clumpSectorSpread = 3;
for (x = 0; x < clumpSectorSpread; x++)
{
for (y = 0; y < clumpSectorSpread; y++)
{
int sprdX = floor(clumpSectorSpread * -0.5) + x + rndX;
int sprdY = floor(clumpSectorSpread * -0.5) + y + rndY;
if (sprdX < 0 || sprdX >= distrib_SectorNumX)
continue;
if (sprdY < 0 || sprdY >= distrib_SectorNumY)
continue;
vector sprdPos = Vector(fsum(sprdX), fsum(sprdY), 0);
float distPct = fsum(VectorLength(clumpPos - sprdPos) / clumpSectorSpread);
distPct = 1 - distPct;
if (distPct <= 0)
continue;
distPct = distPct * distPct;
distPct = distPct * distPct;
if (distPct <= 0.05)
continue;
amt = floor(frand(0.9, 1.1) * maxPerSector / clumpSectorSpread * distPct);
if (frand(0, 1) < 0.25)
clamp amt<5, resourceToDistribute>;
else
clamp amt<0, resourceToDistribute>;
AddAmountToSector(amt, sprdX, sprdY);
Changed[sprdX][sprdY] = false;
resourceToDistribute -= amt;
if (resourceToDistribute <= 0)
break;
}
if (resourceToDistribute <= 0)
break;
}
}
}
randomize(-1); // Randomize seed again
}
//----------------------------------------------------------
void Resource_Base::MPSynchSector(int sectorX, int sectorY)
{
if (!g_Game.IsServer())
return;
if (index < 0)
return;
owner.RP_UpdateResource(index, sectorX, sectorY, Amount[sectorX][sectorY], false);
}
//----------------------------------------------------------
void Resource_Base::DebugDisplayInWorld()
{
for (int x = 0; x < distrib_SectorNumX; x++)
{
for (int y = 0; y < distrib_SectorNumY; y++)
{
float amt = fsum(Amount[x][y]);
float posX = fsum(distrib_SectorNumX * -0.5 + x * owner.loc_sectorSize);
float posY = fsum(distrib_SectorNumY * -0.5 + y * owner.loc_sectorSize);
vector mins = Vector(posX, posY, 0);
vector maxs = mins + Vector(owner.loc_sectorSize, owner.loc_sectorSize, amt / 4000 * 3200);
if (amt > 0)
AddDShape(SHAPE_BBOX, ARGBF(32, displayColor[0], displayColor[1], displayColor[2]), SS_NOZBUFFER|SS_TRANSP|SS_ONCE, mins, maxs);
else
AddDShape(SHAPE_BBOX, ARGBF(32, 0, 0, 0), SS_NOZBUFFER|SS_TRANSP|SS_ONCE, mins, maxs);
}
}
}
//----------------------------------------------------------
void Resource_Base::DebugHighlightSectorInWorld(int x, int y)
{
float amt = fsum(Amount[x][y]);
float posX = fsum(distrib_SectorNumX * -0.5 + x * owner.loc_sectorSize);
float posY = fsum(distrib_SectorNumY * -0.5 + y * owner.loc_sectorSize);
vector mins = Vector(posX, posY, 0);
vector maxs = mins + Vector(owner.loc_sectorSize, owner.loc_sectorSize, amt / 4000 * 3200);
AddDShape(SHAPE_BBOX, ARGBF(64, 255, 255, 0), SS_NOZBUFFER|SS_TRANSP|SS_ONCE, mins, maxs);
}
//----------------------------------------------------------
void Location::Location()
{
loc_sectorSize = RESOURCE_SECTOR_SIZE;
type = LocationObjectType;
locked = false;
hidden = false;
ResourcesNum = 0;
for (int i = 0; i < RESOURCE_MAXTYPES; i++)
{
Resources[i] = NULL;
}
ClearDiscoveredSectors();
ClearStoreObjects();
ClearStoredBBlockGroups();
ClearMPCustom();
StoredScnFileVersion = SCN_FILE_VERSION;
}
//----------------------------------------------------------
void Location::~Location()
{
ClearStoreObjects();
ClearStoredBBlockGroups();
DestroyVehicles();
DestroyRagdolls();
DestroyScienceTargets();
DestroyResources();
}
//----------------------------------------------------------
bool Location::IsHidden()
{
return hidden;
}
//----------------------------------------------------------
bool Location::IsLocked()
{
return locked;
}
//----------------------------------------------------------
void Location::Hide(bool hide)
{
hidden = hide;
}
//----------------------------------------------------------
void Location::Unlock()
{
locked = false;
}
//----------------------------------------------------------
void Location::CalculateResourceSectorNums()
{
ResourcesSectorNum_X = sum(ceil(loc_worldsize[0]) / loc_sectorSize);
ResourcesSectorNum_Y = sum(ceil(loc_worldsize[1]) / loc_sectorSize);
clamp ResourcesSectorNum_X<0, RESOURCE_SECTOR_MAXNUM>;
clamp ResourcesSectorNum_Y<0, RESOURCE_SECTOR_MAXNUM>;
}
//----------------------------------------------------------
void Location::SetLastSelectedMission(ScienceTarget mission)
{
lastSelectedMission = mission;
}
//----------------------------------------------------------
int Location::GetEnabledMissionsCount()
{
local int count = 0;
for(local int n = 0; n < scienceTargetsCount; n++)
{
local ScienceTarget mission = scienceTargets[n];
if (mission.IsCurrentlyCompletable())
count++;
}
return count;
}
//----------------------------------------------------------
VehicleObject Location::FindVehicle(string name)
{
for(int n = 0; n < vehiclesCount; n++)
{
VehicleObject vehicle = vehicles[n];
if(vehicle.name == name)
return vehicles[n];
}
return NULL;
}
//----------------------------------------------------------
VehicleObject Location::FindVehicleByCFGAndTeam(string cfgPath, int team)
{
strlower(cfgPath);
for(int n = 0; n < vehiclesCount; n++)
{
VehicleObject vehicle = vehicles[n];
int vehTeam = vehicle.Team;
string vehCfg = vehicle.cfgFile;
strlower(vehCfg);
if(vehCfg == cfgPath && vehTeam == team)
return vehicles[n];
}
return NULL;
}
//----------------------------------------------------------
VehicleObject Location::FindVehicleByCFG(string cfgPath)
{
strlower(cfgPath);
for(int n = 0; n < vehiclesCount; n++)
{
VehicleObject vehicle = vehicles[n];
string vehCfg = vehicle.cfgFile;
strlower(vehCfg);
if(vehCfg == cfgPath)
return vehicles[n];
}
return NULL;
}
//----------------------------------------------------------
VehicleObject Location::FindVehicleByStoreID(int storeID)
{
for(int n = 0; n < vehiclesCount; n++)
{
VehicleObject vehicle = vehicles[n];
if(vehicle.Store_ID == storeID)
return vehicles[n];
}
return NULL;
}
//----------------------------------------------------------
int Location::FindVehicleIndex(VehicleObject vehicle)
{
for(int n = 0; n < vehiclesCount; n++)
{
VehicleObject veh = vehicles[n];
if(veh == vehicle)
return n;
}
return -1;
}
//----------------------------------------------------------
RagdollObject Location::FindRagdollByStoreID(int storeID)
{
for(int n = 0; n < ragdollsCount; n++)
{
RagdollObject ragdoll = ragdolls[n];
if(ragdoll.Store_ID == storeID)
return ragdoll;
}
return NULL;
}
//----------------------------------------------------------
int Location::FindRagdollIndex(RagdollObject ragdollStore)
{
for(int n = 0; n < ragdollsCount; n++)
{
RagdollObject ragdoll = ragdolls[n];
if(ragdoll == ragdollStore)
return n;
}
return -1;
}
//----------------------------------------------------------
void RagdollObject::SetOwnerPtr(Location location)
{
owner = location;
}
//----------------------------------------------------------
void VehicleObject::SetOwnerPtr(Location location)
{
owner = location;
}
//----------------------------------------------------------
void VehicleObject::SetMission(ScienceTarget mis)
{
mission = mis;
}
//----------------------------------------------------------
ScienceTarget VehicleObject::GetMission()
{
return mission;
}
//----------------------------------------------------------
CharacterObject Location::CreateCharacter(string name)
{
CharacterObject character = NULL;
if (vehiclesCount < MAX_VEHICLES_PER_LOCATION) {
character = new CharacterObject();
character.SetOwnerPtr(this);
character.name = name;
vehicles[vehiclesCount] = character;
vehiclesCount++;
}
return character;
}
//----------------------------------------------------------
CharacterObject Location::CreateNamedCharacter()
{
return CreateCharacter( g_Campaign.GenerateCharacterName() );
}
//----------------------------------------------------------
VehicleObject Location::CreateVehicle(string name)
{
VehicleObject vehicle = NULL;
if (vehiclesCount < MAX_VEHICLES_PER_LOCATION) {
vehicle = new VehicleObject();
vehicle.SetOwnerPtr(this);
vehicle.name = name;
vehicles[vehiclesCount] = vehicle;
vehiclesCount++;
}
return vehicle;
}
//----------------------------------------------------------
VehicleObject Location::CreateNamedVehicle()
{
return CreateVehicle( g_Campaign.GenerateVehicleName() );
}
//----------------------------------------------------------
RagdollObject Location::CreateRagdoll(string name)
{
RagdollObject ragdollStore = NULL;
if (ragdollsCount < MAX_RAGDOLLS_PER_LOCATION) {
ragdollStore = new RagdollObject();
ragdollStore.SetOwnerPtr(this);
ragdolls[ragdollsCount] = ragdollStore;
ragdollsCount++;
}
return ragdollStore;
}
//----------------------------------------------------------
void Location::DestroyVehicleInstance(VehicleObject vehicle)
{
if(vehicle)
{
delete vehicle;
vehicle = NULL;
}
}
//----------------------------------------------------------
void Location::DestroyRagdollInstance(RagdollObject ragdollStore)
{
if(ragdollStore)
{
delete ragdollStore;
ragdollStore = NULL;
}
}
//----------------------------------------------------------
void Location::DestroyVehicles()
{
for(int n = vehiclesCount - 1; n >= 0; n--)
{
VehicleObject target = vehicles[n];
DestroyVehicleInstance(target);
vehicles[n] = NULL;
}
vehiclesCount = 0;
}
//----------------------------------------------------------
void Location::DestroyRagdolls()
{
for(int n = ragdollsCount - 1; n >= 0; n--)
{
RagdollObject target = ragdolls[n];
DestroyRagdollInstance(target);
ragdolls[n] = NULL;
}
ragdollsCount = 0;
}
//----------------------------------------------------------
void Location::DestroyVehicleByIndex(int index)
{
int lastIndex = vehiclesCount - 1;
if(lastIndex < 0)
return;
if(index > lastIndex)
return;
DestroyVehicleInstance(vehicles[index]);
vehicles[index] = NULL;
vehiclesCount--;
for(int n = index; n < vehiclesCount; n++)
vehicles[n] = vehicles[n + 1];
}
//----------------------------------------------------------
void Location::DestroyRagdollByIndex(int index)
{
int lastIndex = ragdollsCount - 1;
if(lastIndex < 0)
return;
if(index > lastIndex)
return;
DestroyRagdollInstance(ragdolls[index]);
ragdolls[index] = NULL;
ragdollsCount--;
for(int n = index; n < ragdollsCount; n++)
ragdolls[n] = ragdolls[n + 1];
}
//----------------------------------------------------------
void Location::DestroyVehicle(VehicleObject vehicle)
{
int index = FindVehicleIndex(vehicle);
if(index >= 0)
DestroyVehicleByIndex(index);
}
//----------------------------------------------------------
void Location::DestroyRagdoll(RagdollObject ragdollStore)
{
int index = FindRagdollIndex(ragdollStore);
if(index >= 0)
DestroyRagdollByIndex(index);
}
//----------------------------------------------------------
StoreObject_Base Location::CreateStoreObject(string objType)
{
StoreObject_Base objStore = NULL;
if (objectsCount < MAX_OBJECTS_PER_LOCATION) {
if (objType == "StaticObject") objStore = new StaticObject;
if (objType == "DynamicObject") objStore = new DynamicObject;
if (objType == "ProjectileObject") objStore = new ProjectileObject;
if (objType == "ParticleObject") objStore = new ParticleObject;
if (objType == "EventFXObject") objStore = new EventFXObject;
if (objType == "EventScriptObject") objStore = new EventScriptObject;
if (objType == "EventTimerObject") objStore = new EventTimerObject;
if (objType == "TriggerObject") objStore = new TriggerObject;
if (objType == "WaterZoneObject") objStore = new WaterZoneObject;
if (objType == "BuildingBlockObject") objStore = new BuildingBlockObject;
if (objStore) {
objects[objectsCount] = objStore;
objectsCount++;
}
}
else
CallError("CreateStoreObject()", "Cannot create new storage object, objectsCount reached maximum of " + itoa(MAX_OBJECTS_PER_LOCATION) + "!!!");
return objStore;
}
//----------------------------------------------------------
void Location::AddCreatedStoreObject(StoreObject_Base storeObj)
{
if (objectsCount < MAX_OBJECTS_PER_LOCATION) {
objects[objectsCount] = storeObj;
objectsCount++;
}
else
CallError("AddCreatedStoreObject()", "Cannot add storage object, objectsCount reached maximum of " + itoa(MAX_OBJECTS_PER_LOCATION) + "!!!");
}
//----------------------------------------------------------
void Location::StoreObject(TKOM_Entity tkomEnt)
{
Object_BuildingBlock ent_buildBlock = NULL;
Object_WaterZone ent_waterZone = NULL;
Object_Static ent_statObj = NULL;
Object_Dynamic ent_dynObj = NULL;
Object_InventoryItem ent_invItem = NULL;
Projectile ent_projObj = NULL;
ParticleEmitter ent_ptcObj = NULL;
Event_FX ent_evFXObj = NULL;
Event_Script ent_evScptObj = NULL;
Event_Timer ent_evTimObj = NULL;
Trigger_Base ent_trigObj = NULL;
if (!g_Game.IsClient())
tkomEnt.SetNoUpdate(false);
if (IsInherited(tkomEnt, Type("Object_BuildingBlock"))) ent_buildBlock = (Object_BuildingBlock)tkomEnt;
if (IsInherited(tkomEnt, Type("Object_WaterZone"))) ent_waterZone = (Object_WaterZone)tkomEnt;
if (IsInherited(tkomEnt, Type("Object_Static"))) ent_statObj = (Object_Static)tkomEnt;
if (IsInherited(tkomEnt, Type("Object_Dynamic"))) ent_dynObj = (Object_Dynamic)tkomEnt;
if (IsInherited(tkomEnt, Type("Object_InventoryItem"))) ent_invItem = (Object_InventoryItem)tkomEnt;
if (IsInherited(tkomEnt, Type("Projectile"))) ent_projObj = (Projectile)tkomEnt;
if (IsInherited(tkomEnt, Type("ParticleEmitter"))) ent_ptcObj = (ParticleEmitter)tkomEnt;
if (IsInherited(tkomEnt, Type("Event_FX"))) ent_evFXObj = (Event_FX)tkomEnt;
if (IsInherited(tkomEnt, Type("Event_Script"))) ent_evScptObj = (Event_Script)tkomEnt;
if (IsInherited(tkomEnt, Type("Event_Timer"))) ent_evTimObj = (Event_Timer)tkomEnt;
if (IsInherited(tkomEnt, Type("Trigger_Base"))) ent_trigObj = (Trigger_Base)tkomEnt;
StoreObject_Base objStore = NULL;
if (ent_buildBlock) {
objStore = CreateStoreObject("BuildingBlockObject");
BuildingBlockObject buildBlockObj = NULL;
if (objStore) buildBlockObj = (BuildingBlockObject)objStore;
if (buildBlockObj) {
buildBlockObj.inventory = ent_buildBlock.inventory;
if (buildBlockObj.inventory)
{
buildBlockObj.inventory.SetParent(buildBlockObj, ent_buildBlock.GetID(), 0);
buildBlockObj.inventory.DeleteItemScripts();
}
buildBlockObj.configFile = String(ent_buildBlock.ConfigFile);
buildBlockObj.modelPath = String(ent_buildBlock.ModelPath);
buildBlockObj.remapPath = String(ent_buildBlock.ModelRemap);
buildBlockObj.customScript = String(ent_buildBlock.CustomScript);
buildBlockObj.activateText = String(ent_buildBlock.ActivateText);
buildBlockObj.activateImage = String(ent_buildBlock.ActivateImage);
buildBlockObj.fxPath = String(ent_buildBlock.ContactPtcSnd);
if (ent_buildBlock.IsDynamic) {
buildBlockObj.worldAngVelocity = dBodyGetAngularVelocity(ent_buildBlock);
buildBlockObj.worldVelocity = GetVelocity(ent_buildBlock);
} else {
buildBlockObj.worldAngVelocity = ZeroVec;
buildBlockObj.worldVelocity = ZeroVec;
}
buildBlockObj.modelMass = ent_buildBlock.ModelMass;
buildBlockObj.genInt = ent_buildBlock.GenInt;
buildBlockObj.genFloat = ent_buildBlock.GenFloat;
buildBlockObj.genVec = ent_buildBlock.GenVec;
buildBlockObj.SetGenString(ent_buildBlock.GenString);
buildBlockObj.custom_GridSnap = ent_buildBlock.Custom_GridSnap;
buildBlockObj.buildPctTime = ent_buildBlock.BuildPctTime;
buildBlockObj.buildTime = ent_buildBlock.BuildTime;
buildBlockObj.isInTransition = ent_buildBlock.IsInTransition;
buildBlockObj.isActivated = ent_buildBlock.IsActivated;
buildBlockObj.isDynamic = ent_buildBlock.IsDynamic;
for (int bblockPwrpt = 0; bblockPwrpt < POWERPOINTS_MAX; bblockPwrpt++) {
buildBlockObj.powerpoint_pos[bblockPwrpt] = ent_buildBlock.powerpoint_pos[bblockPwrpt];
buildBlockObj.powerpoint_ang[bblockPwrpt] = ent_buildBlock.powerpoint_ang[bblockPwrpt];
buildBlockObj.powerpoint_out[bblockPwrpt] = ent_buildBlock.powerpoint_out[bblockPwrpt];
buildBlockObj.powerpoint_connect_ID[bblockPwrpt] = ent_buildBlock.powerpoint_connect_ID[bblockPwrpt];
buildBlockObj.powerpoint_connect_SubID[bblockPwrpt] = ent_buildBlock.powerpoint_connect_SubID[bblockPwrpt];
buildBlockObj.powerpoint_connect_Slot[bblockPwrpt] = ent_buildBlock.powerpoint_connect_Slot[bblockPwrpt];
}
buildBlockObj.powerpoint_num = ent_buildBlock.powerpoint_num;
for (int bblockSeat = 0; bblockSeat < BUILDBLOCK_MAXCHARACTERSEATS; bblockSeat++) {
buildBlockObj.seats_Pos[bblockSeat] = ent_buildBlock.Seats_Pos[bblockSeat];
buildBlockObj.seats_Ang[bblockSeat] = ent_buildBlock.Seats_Ang[bblockSeat];
buildBlockObj.seats_ExitPos[bblockSeat] = ent_buildBlock.Seats_ExitPos[bblockSeat];
buildBlockObj.seats_ExitAng[bblockSeat] = ent_buildBlock.Seats_ExitAng[bblockSeat];
buildBlockObj.seats_CanSleep[bblockSeat] = ent_buildBlock.Seats_CanSleep[bblockSeat];
buildBlockObj.seats_InAnim[bblockSeat] = String(ent_buildBlock.Seats_InAnim[bblockSeat]);
buildBlockObj.seats_OutAnim[bblockSeat] = String(ent_buildBlock.Seats_OutAnim[bblockSeat]);
buildBlockObj.seats_Anim[bblockSeat] = String(ent_buildBlock.Seats_Anim[bblockSeat]);
buildBlockObj.seats_CharacterID[bblockSeat] = ent_buildBlock.Seats_CharacterID[bblockSeat];
}
buildBlockObj.seats_Num = ent_buildBlock.Seats_Num;
for (int bblockSlot = 0; bblockSlot < BUILDBLOCK_SLOTSMAX; bblockSlot++) {
buildBlockObj.slots_Types[bblockSlot] = String(ent_buildBlock.Slots_Types[bblockSlot]);
buildBlockObj.slots_LinkEntID[bblockSlot] = ent_buildBlock.Slots_LinkEntID[bblockSlot];
buildBlockObj.slots_Pos[bblockSlot] = ent_buildBlock.Slots_Pos[bblockSlot];
buildBlockObj.slots_Ang[bblockSlot] = ent_buildBlock.Slots_Ang[bblockSlot];
buildBlockObj.slots_SingleDir[bblockSlot] = ent_buildBlock.Slots_SingleDir[bblockSlot];
buildBlockObj.slots_NoWorldSnap[bblockSlot] = ent_buildBlock.Slots_NoWorldSnap[bblockSlot];
buildBlockObj.slots_PreventDisassemble[bblockSlot] = ent_buildBlock.Slots_PreventDisassemble[bblockSlot];
buildBlockObj.slots_SealsAtmosphere[bblockSlot] = ent_buildBlock.Slots_SealsAtmosphere[bblockSlot];
}
buildBlockObj.slotsNum = ent_buildBlock.SlotsNum;
for (int bblockResStore = 0; bblockResStore < BUILDBLOCK_RESSTOREMAX; bblockResStore++) {
buildBlockObj.resStore_ResName[bblockResStore] = String(ent_buildBlock.ResStore_ResName[bblockResStore]);
buildBlockObj.resStore_Amount[bblockResStore] = ent_buildBlock.ResStore_Amount[bblockResStore];
buildBlockObj.resStore_MaxAmount[bblockResStore] = ent_buildBlock.ResStore_MaxAmount[bblockResStore];
}
buildBlockObj.resStoreNum = ent_buildBlock.ResStoreNum;
for (int bblockResCost = 0; bblockResCost < BUILDBLOCK_RESCOSTMAX; bblockResCost++) {
buildBlockObj.resCost_ResName[bblockResCost] = String(ent_buildBlock.ResCost_ResName[bblockResCost]);
buildBlockObj.resCost_Amount[bblockResCost] = ent_buildBlock.ResCost_Amount[bblockResCost];
}
buildBlockObj.resCostNum = ent_buildBlock.ResCostNum;
for (int bblockAtmoNorm = 0; bblockAtmoNorm < BUILDBLOCK_ATMONORMALSMAX; bblockAtmoNorm++) {
buildBlockObj.atmoNorms_Pos[bblockAtmoNorm] = ent_buildBlock.AtmoNorms_Pos[bblockAtmoNorm];
buildBlockObj.atmoNorms_Dir[bblockAtmoNorm] = ent_buildBlock.AtmoNorms_Dir[bblockAtmoNorm];
}
buildBlockObj.atmoNormsNum = ent_buildBlock.AtmoNormsNum;
for (int bblockAtmZns = 0; bblockAtmZns < BUILDBLOCK_ATMOZONESMAX; bblockAtmZns++) {
buildBlockObj.atmoWholeZones_Mins[bblockAtmZns] = ent_buildBlock.AtmoWholeZones_Mins[bblockAtmZns];
buildBlockObj.atmoWholeZones_Maxs[bblockAtmZns] = ent_buildBlock.AtmoWholeZones_Maxs[bblockAtmZns];
}
buildBlockObj.atmoWholeZonesNum = ent_buildBlock.AtmoWholeZonesNum;
buildBlockObj.move_Start_Mat[0] = ent_buildBlock.Move_Start_Mat[0];
buildBlockObj.move_Start_Mat[1] = ent_buildBlock.Move_Start_Mat[1];
buildBlockObj.move_Start_Mat[2] = ent_buildBlock.Move_Start_Mat[2];
buildBlockObj.move_Start_Mat[3] = ent_buildBlock.Move_Start_Mat[3];
buildBlockObj.move_End_Pos = ent_buildBlock.Move_End_Pos;
buildBlockObj.move_End_Ang = ent_buildBlock.Move_End_Ang;
buildBlockObj.move_PctTime = ent_buildBlock.Move_PctTime;
buildBlockObj.move_Time = ent_buildBlock.Move_Time;
buildBlockObj.move_DelayTime = ent_buildBlock.Move_DelayTime;
buildBlockObj.move_OnTouch = ent_buildBlock.Move_OnTouch;
buildBlockObj.move_OnActivate = ent_buildBlock.Move_OnActivate;
buildBlockObj.move_State = ent_buildBlock.Move_State;
buildBlockObj.move_Stopped = ent_buildBlock.Move_Stopped;
buildBlockObj.anim_Rate = ent_buildBlock.Anim_Rate;
buildBlockObj.anim_Time = ent_buildBlock.Anim_Time;
buildBlockObj.anim_State = ent_buildBlock.Anim_State;
buildBlockObj.demountMat[0] = ent_buildBlock.DemountMat[0];
buildBlockObj.demountMat[1] = ent_buildBlock.DemountMat[1];
buildBlockObj.demountMat[2] = ent_buildBlock.DemountMat[2];
buildBlockObj.demountMat[3] = ent_buildBlock.DemountMat[3];
buildBlockObj.demountGround = ent_buildBlock.DemountGround;
buildBlockObj.transitionMat_Start[0] = ent_buildBlock.TransitionMat_Start[0];
buildBlockObj.transitionMat_Start[1] = ent_buildBlock.TransitionMat_Start[1];
buildBlockObj.transitionMat_Start[2] = ent_buildBlock.TransitionMat_Start[2];
buildBlockObj.transitionMat_Start[3] = ent_buildBlock.TransitionMat_Start[3];
buildBlockObj.transitionMat_End[0] = ent_buildBlock.TransitionMat_End[0];
buildBlockObj.transitionMat_End[1] = ent_buildBlock.TransitionMat_End[1];
buildBlockObj.transitionMat_End[2] = ent_buildBlock.TransitionMat_End[2];
buildBlockObj.transitionMat_End[3] = ent_buildBlock.TransitionMat_End[3];
buildBlockObj.transitionMat_Time = ent_buildBlock.TransitionMat_Time;
buildBlockObj.transitionMat_ToGround = ent_buildBlock.TransitionMat_ToGround;
buildBlockObj.transitionMat_NoWorldSnap = ent_buildBlock.TransitionMat_NoWorldSnap;
buildBlockObj.transitionMat_Demount = ent_buildBlock.TransitionMat_Demount;
GetMatrix4(ent_buildBlock, buildBlockObj.worldMatrix);
buildBlockObj.worldID = ent_buildBlock.GetID();
buildBlockObj.isNetworkObject = ent_buildBlock.isNetworkEntity;
}
}
if (ent_waterZone) {
objStore = CreateStoreObject("WaterZoneObject");
WaterZoneObject wtrZnObj = NULL;
if (objStore) wtrZnObj = (WaterZoneObject)objStore;
if (wtrZnObj) {
wtrZnObj.width = ent_waterZone.width;
wtrZnObj.length = ent_waterZone.length;
wtrZnObj.depth = ent_waterZone.depth;
wtrZnObj.density = ent_waterZone.density;
wtrZnObj.watercolor = ent_waterZone.watercolor;
wtrZnObj.murkiness = ent_waterZone.murkiness;
wtrZnObj.caustic = ent_waterZone.caustic;
wtrZnObj.watercurrent = ent_waterZone.watercurrent;
wtrZnObj.disableEffects = ent_waterZone.disableEffects;
GetMatrix4(ent_waterZone, wtrZnObj.worldMatrix);
wtrZnObj.worldID = ent_waterZone.GetID();
wtrZnObj.isNetworkObject = ent_waterZone.isNetworkEntity;
}
}
if (ent_statObj) {
objStore = CreateStoreObject("StaticObject");
StaticObject statObj = NULL;
if (objStore) statObj = (StaticObject)objStore;
if (statObj) {
statObj.modelPath = String(ent_statObj.ModelPath);
statObj.remapPath = String(ent_statObj.ModelRemap);
GetMatrix4(ent_statObj, statObj.worldMatrix);
statObj.worldID = ent_statObj.GetID();
statObj.isNetworkObject = ent_statObj.isNetworkEntity;
}
}
if (ent_dynObj) {
objStore = CreateStoreObject("DynamicObject");
DynamicObject dynObj = NULL;
if (objStore) dynObj = (DynamicObject)objStore;
if (dynObj) {
dynObj.modelPath = String(ent_dynObj.ModelPath);
dynObj.remapPath = String(ent_dynObj.ModelRemap);
dynObj.fxPath = String(ent_dynObj.ContactPtcSnd);
dynObj.worldAngVelocity = dBodyGetAngularVelocity(ent_dynObj);
dynObj.worldVelocity = GetVelocity(ent_dynObj);
dynObj.modelMass = ent_dynObj.ModelMass;
GetMatrix4(ent_dynObj, dynObj.worldMatrix);
dynObj.worldID = ent_dynObj.GetID();
dynObj.isNetworkObject = ent_dynObj.isNetworkEntity;
}
}
if (ent_invItem) {
ent_invItem.UpdateStorageWorldData();
AddCreatedStoreObject(ent_invItem.storage);
ent_invItem.storage.DeleteCustomScript();
}
if (ent_projObj) {
objStore = CreateStoreObject("ProjectileObject");
ProjectileObject projObj = NULL;
if (objStore) projObj = (ProjectileObject)objStore;
if (projObj) {
projObj.modelPath = String(ent_projObj.ModelPath);
projObj.fxPath = String(ent_projObj.ContactPtcSnd);
projObj.ptcPath = String(ent_projObj.PtcPath);
projObj.worldAngVelocity = dBodyGetAngularVelocity(ent_projObj);
projObj.worldVelocity = GetVelocity(ent_projObj);
projObj.modelMass = GetObjectMass(ent_projObj);
projObj.deathTime = ent_projObj.DeathTime;
projObj.deathOnImpact = ent_projObj.DeathByImpact;
GetMatrix4(ent_projObj, projObj.worldMatrix);
projObj.worldID = ent_projObj.GetID();
projObj.isNetworkObject = ent_projObj.isNetworkEntity;
}
}
if (ent_ptcObj) {
if (ent_ptcObj.playedTime < ent_ptcObj.maxPlayTime || ent_ptcObj.maxPlayTime == -1) {
objStore = CreateStoreObject("ParticleObject");
ParticleObject ptcObj = NULL;
if (objStore) ptcObj = (ParticleObject)objStore;
if (ptcObj) {
ptcObj.ptcPath = String(ent_ptcObj.ParticleToPlay);
ptcObj.ptcTime = ent_ptcObj.playedTime;
GetMatrix4(ent_ptcObj, ptcObj.worldMatrix);
ptcObj.worldID = ent_ptcObj.GetID();
ptcObj.isNetworkObject = ent_ptcObj.isNetworkEntity;
ptcObj.priority = ent_ptcObj.priority;
}
}
}
if (ent_evFXObj) {
objStore = CreateStoreObject("EventFXObject");
EventFXObject evFXObj = NULL;
if (objStore) evFXObj = (EventFXObject)objStore;
if (evFXObj) {
evFXObj.sndPath = String(ent_evFXObj.event_snd);
evFXObj.ptcPath = String(ent_evFXObj.event_ptc);
GetMatrix4(ent_evFXObj, evFXObj.worldMatrix);
evFXObj.worldID = ent_evFXObj.GetID();
evFXObj.isNetworkObject = ent_evFXObj.isNetworkEntity;
}
}
if (ent_evScptObj) {
objStore = CreateStoreObject("EventScriptObject");
EventScriptObject evScptObj = NULL;
if (objStore) evScptObj = (EventScriptObject)objStore;
if (evScptObj) {
evScptObj.scriptPath = String(ent_evScptObj.event_scpt);
GetMatrix4(ent_evScptObj, evScptObj.worldMatrix);
evScptObj.worldID = ent_evScptObj.GetID();
evScptObj.isNetworkObject = ent_evScptObj.isNetworkEntity;
}
}
if (ent_evTimObj) {
objStore = CreateStoreObject("EventTimerObject");
EventTimerObject evTimObj = NULL;
if (objStore) evTimObj = (EventTimerObject)objStore;
if (evTimObj) {
evTimObj.CounterRunning = ent_evTimObj.CounterRunning;
evTimObj.CounterCurrent = ent_evTimObj.CounterCurrent;
evTimObj.CounterTarget = ent_evTimObj.CounterTarget;
evTimObj.CounterRepeatsCurrent = ent_evTimObj.CounterRepeatsCurrent;
evTimObj.CounterRepeatsTotal = ent_evTimObj.CounterRepeatsTotal;
evTimObj.LinkEntIDs = ent_evTimObj.LinkEntIDs;
GetMatrix4(ent_evTimObj, evTimObj.worldMatrix);
evTimObj.worldID = ent_evTimObj.GetID();
evTimObj.isNetworkObject = ent_evTimObj.isNetworkEntity;
}
}
if (ent_trigObj) {
objStore = CreateStoreObject("TriggerObject");
TriggerObject trgObj = NULL;
if (objStore) trgObj = (TriggerObject)objStore;
if (trgObj) {
trgObj.radius = ent_trigObj.radius;
trgObj.height = ent_trigObj.height;
trgObj.trigOnExitType = ent_trigObj.trigger_onExit;
trgObj.trigOnStartType = ent_trigObj.trigger_onStart;
trgObj.trigVehicle = ent_trigObj.trigger_vehicle;
trgObj.trigProjectile = ent_trigObj.trigger_projectile;
trgObj.trigDynamic = ent_trigObj.trigger_dynamic;
trgObj.trigOnce = ent_trigObj.trigger_once;
trgObj.triggered = ent_trigObj.triggered;
GetMatrix4(ent_trigObj, trgObj.worldMatrix);
trgObj.worldID = ent_trigObj.GetID();
trgObj.isNetworkObject = ent_trigObj.isNetworkEntity;
for (int lN = 0; lN < TRIGGER_MAXLINKS; lN++) {
trgObj.linkIDs[lN] = ent_trigObj.linkIDs[lN];
}
}
}
}
//----------------------------------------------------------
void Location::RestoreObjects()
{
vector mat[4];
float spd;
for(int n = 0; n < objectsCount; n++)
{
StoreObject_Base objStore = objects[n];
if (objStore != NULL) {
mat[0] = objStore.worldMatrix[0];
mat[1] = objStore.worldMatrix[1];
mat[2] = objStore.worldMatrix[2];
mat[3] = objStore.worldMatrix[3];
StaticObject statObj = NULL;
DynamicObject dynObj = NULL;
ProjectileObject projObj = NULL;
ParticleObject ptcObj = NULL;
EventFXObject evFXObj = NULL;
EventScriptObject evScptObj = NULL;
EventTimerObject evTimObj = NULL;
TriggerObject trgObj = NULL;
WaterZoneObject wtrZnObj = NULL;
BuildingBlockObject buildBlockObj = NULL;
InventoryItemObject invItemObj = NULL;
if (IsInherited(objStore, Type("StaticObject"))) statObj = (StaticObject)objStore;
if (IsInherited(objStore, Type("DynamicObject"))) dynObj = (DynamicObject)objStore;
if (IsInherited(objStore, Type("ProjectileObject"))) projObj = (ProjectileObject)objStore;
if (IsInherited(objStore, Type("ParticleObject"))) ptcObj = (ParticleObject)objStore;
if (IsInherited(objStore, Type("EventFXObject"))) evFXObj = (EventFXObject)objStore;
if (IsInherited(objStore, Type("EventScriptObject"))) evScptObj = (EventScriptObject)objStore;
if (IsInherited(objStore, Type("EventTimerObject"))) evTimObj = (EventTimerObject)objStore;
if (IsInherited(objStore, Type("TriggerObject"))) trgObj = (TriggerObject)objStore;
if (IsInherited(objStore, Type("WaterZoneObject"))) wtrZnObj = (WaterZoneObject)objStore;
if (IsInherited(objStore, Type("BuildingBlockObject"))) buildBlockObj = (BuildingBlockObject)objStore;
if (IsInherited(objStore, Type("InventoryItemObject"))) invItemObj = (InventoryItemObject)objStore;
int entNetwork = NETWORK_USEDEFAULT;
if (objStore.isNetworkObject)
entNetwork = NETWORK_SETTRUE;
else
entNetwork = NETWORK_SETFALSE;
bool networkEntity = false;
if (buildBlockObj) {
Object_BuildingBlock ent_buildBlock = new Object_BuildingBlock(buildBlockObj.configFile, mat[0], mat[1], mat[2], mat[3], buildBlockObj.fxPath, buildBlockObj.modelPath, buildBlockObj.remapPath, buildBlockObj.modelMass, buildBlockObj.isDynamic, buildBlockObj.isNetworkObject);
ent_buildBlock.inventory = buildBlockObj.inventory;
if (ent_buildBlock.inventory)
{
ent_buildBlock.inventory.SetParent(ent_buildBlock, buildBlockObj.worldID, 0);
ent_buildBlock.inventory.RestoreItemIDs();
ent_buildBlock.inventory.LoadItemScripts();
}
ent_buildBlock.GenInt = buildBlockObj.genInt;
ent_buildBlock.GenFloat = buildBlockObj.genFloat;
ent_buildBlock.GenVec = buildBlockObj.genVec;
ent_buildBlock.SetGenString(buildBlockObj.genString);
ent_buildBlock.Custom_GridSnap = buildBlockObj.custom_GridSnap;
ent_buildBlock.BuildPctTime = buildBlockObj.buildPctTime;
ent_buildBlock.BuildTime = buildBlockObj.buildTime;
ent_buildBlock.IsInTransition = buildBlockObj.isInTransition;
ent_buildBlock.IsActivated = buildBlockObj.isActivated;
for (int bblockPwrpt = 0; bblockPwrpt < buildBlockObj.powerpoint_num; bblockPwrpt++) {
ent_buildBlock.AddPowerpoint(buildBlockObj.powerpoint_pos[bblockPwrpt], buildBlockObj.powerpoint_ang[bblockPwrpt], buildBlockObj.powerpoint_out[bblockPwrpt]);
ent_buildBlock.SetPowerpointConnection(bblockPwrpt, buildBlockObj.powerpoint_connect_ID[bblockPwrpt], buildBlockObj.powerpoint_connect_SubID[bblockPwrpt], buildBlockObj.powerpoint_connect_Slot[bblockPwrpt]);
}
for (int bblockSeat = 0; bblockSeat < buildBlockObj.seats_Num; bblockSeat++) {
ent_buildBlock.AddSeat(buildBlockObj.seats_Pos[bblockSeat], buildBlockObj.seats_Ang[bblockSeat], buildBlockObj.seats_ExitPos[bblockSeat], buildBlockObj.seats_ExitAng[bblockSeat], buildBlockObj.seats_CanSleep[bblockSeat], buildBlockObj.seats_InAnim[bblockSeat], buildBlockObj.seats_OutAnim[bblockSeat], buildBlockObj.seats_Anim[bblockSeat]);
ent_buildBlock.SetSeatCharacterByID(bblockSeat, buildBlockObj.seats_CharacterID[bblockSeat]);
}
for (int bblockSlot = 0; bblockSlot < buildBlockObj.slotsNum; bblockSlot++) {
ent_buildBlock.AddSlot(buildBlockObj.slots_Pos[bblockSlot], buildBlockObj.slots_Ang[bblockSlot], buildBlockObj.slots_Types[bblockSlot], buildBlockObj.slots_SingleDir[bblockSlot], buildBlockObj.slots_NoWorldSnap[bblockSlot], buildBlockObj.slots_PreventDisassemble[bblockSlot], buildBlockObj.slots_SealsAtmosphere[bblockSlot], buildBlockObj.slots_LinkEntID[bblockSlot]);
}
for (int bblockResStore = 0; bblockResStore < buildBlockObj.resStoreNum; bblockResStore++) {
ent_buildBlock.CopyResource(buildBlockObj.resStore_MaxAmount[bblockResStore], buildBlockObj.resStore_Amount[bblockResStore], buildBlockObj.resStore_ResName[bblockResStore]);
}
for (int bblockResCost = 0; bblockResCost < buildBlockObj.resCostNum; bblockResCost++) {
ent_buildBlock.AddResourceCost(buildBlockObj.resCost_ResName[bblockResCost], buildBlockObj.resCost_Amount[bblockResCost]);
}
for (int bblockAtmoNorm = 0; bblockAtmoNorm < buildBlockObj.atmoNormsNum; bblockAtmoNorm++) {
ent_buildBlock.AddAtmoNormal(buildBlockObj.atmoNorms_Pos[bblockAtmoNorm], buildBlockObj.atmoNorms_Dir[bblockAtmoNorm]);
}
for (int bblockAtmZns = 0; bblockAtmZns < buildBlockObj.atmoWholeZonesNum; bblockAtmZns++) {
ent_buildBlock.AddWholeAtmoZone(buildBlockObj.atmoWholeZones_Mins[bblockAtmZns], buildBlockObj.atmoWholeZones_Maxs[bblockAtmZns]);
}
if (buildBlockObj.isDynamic) {
spd = VectorLength(buildBlockObj.worldAngVelocity) + VectorLength(buildBlockObj.worldVelocity);
if (spd > TKOMENTITY_MINVEL) {
dBodySetAngularVelocity(ent_buildBlock, buildBlockObj.worldAngVelocity);
SetVelocity(ent_buildBlock, buildBlockObj.worldVelocity);
} else
MPSafe_SetPhysicsObjectActive(ent_buildBlock, false);
}
else
{
ent_buildBlock.CalculateGlobalSlotMatrices();
ent_buildBlock.CalculateGlobalAtmoNormals();
ent_buildBlock.CalculateGlobalWholeAtmoZones();
}
ent_buildBlock.Move_Start_Mat[0] = buildBlockObj.move_Start_Mat[0];
ent_buildBlock.Move_Start_Mat[1] = buildBlockObj.move_Start_Mat[1];
ent_buildBlock.Move_Start_Mat[2] = buildBlockObj.move_Start_Mat[2];
ent_buildBlock.Move_Start_Mat[3] = buildBlockObj.move_Start_Mat[3];
ent_buildBlock.Move_End_Pos = buildBlockObj.move_End_Pos;
ent_buildBlock.Move_End_Ang = buildBlockObj.move_End_Ang;
ent_buildBlock.Move_PctTime = buildBlockObj.move_PctTime;
ent_buildBlock.Move_Time = buildBlockObj.move_Time;
ent_buildBlock.Move_DelayTime = buildBlockObj.move_DelayTime;
ent_buildBlock.Move_OnTouch = buildBlockObj.move_OnTouch;
ent_buildBlock.Move_OnActivate = buildBlockObj.move_OnActivate;
ent_buildBlock.Move_State = buildBlockObj.move_State;
ent_buildBlock.Move_Stopped = buildBlockObj.move_Stopped;
ent_buildBlock.Anim_Rate = buildBlockObj.anim_Rate;
ent_buildBlock.Anim_Time = buildBlockObj.anim_Time;
ent_buildBlock.Anim_State = buildBlockObj.anim_State;
ent_buildBlock.DemountMat[0] = buildBlockObj.demountMat[0];
ent_buildBlock.DemountMat[1] = buildBlockObj.demountMat[1];
ent_buildBlock.DemountMat[2] = buildBlockObj.demountMat[2];
ent_buildBlock.DemountMat[3] = buildBlockObj.demountMat[3];
ent_buildBlock.DemountGround = buildBlockObj.demountGround;
ent_buildBlock.TransitionMat_Start[0] = buildBlockObj.transitionMat_Start[0];
ent_buildBlock.TransitionMat_Start[1] = buildBlockObj.transitionMat_Start[1];
ent_buildBlock.TransitionMat_Start[2] = buildBlockObj.transitionMat_Start[2];
ent_buildBlock.TransitionMat_Start[3] = buildBlockObj.transitionMat_Start[3];
ent_buildBlock.TransitionMat_End[0] = buildBlockObj.transitionMat_End[0];
ent_buildBlock.TransitionMat_End[1] = buildBlockObj.transitionMat_End[1];
ent_buildBlock.TransitionMat_End[2] = buildBlockObj.transitionMat_End[2];
ent_buildBlock.TransitionMat_End[3] = buildBlockObj.transitionMat_End[3];
ent_buildBlock.TransitionMat_Time = buildBlockObj.transitionMat_Time;
ent_buildBlock.TransitionMat_ToGround = buildBlockObj.transitionMat_ToGround;
ent_buildBlock.TransitionMat_NoWorldSnap = buildBlockObj.transitionMat_NoWorldSnap;
ent_buildBlock.TransitionMat_Demount = buildBlockObj.transitionMat_Demount;
ent_buildBlock.SetSceneID(buildBlockObj.worldID);
ent_buildBlock.SetActivateDisplay(buildBlockObj.activateText, buildBlockObj.activateImage);
ent_buildBlock.LoadCustomScript(buildBlockObj.customScript);
if (ent_buildBlock.bbcontroller)
ent_buildBlock.bbcontroller.BBController_Init(ent_buildBlock);
}
if (wtrZnObj) {
Object_WaterZone ent_waterZone = new Object_WaterZone;
SetMatrix(ent_waterZone, mat);
ent_waterZone.SetSceneID(wtrZnObj.worldID);
ent_waterZone.width = wtrZnObj.width;
ent_waterZone.length = wtrZnObj.length;
ent_waterZone.depth = wtrZnObj.depth;
ent_waterZone.density = wtrZnObj.density;
ent_waterZone.watercolor = wtrZnObj.watercolor;
ent_waterZone.murkiness = wtrZnObj.murkiness;
ent_waterZone.caustic = wtrZnObj.caustic;
ent_waterZone.watercurrent = wtrZnObj.watercurrent;
ent_waterZone.disableEffects = wtrZnObj.disableEffects;
ent_waterZone.UpdateWaterZone();
}
if (statObj)
{
networkEntity = GetNetworkEntityDef(entNetwork, "Object_Static");
if(g_Game.CanCreateEntity( networkEntity )) //do not create network entities on clients
{
Object_Static ent_statObj = new Object_Static(mat[0], mat[1], mat[2], mat[3], statObj.modelPath, statObj.remapPath, networkEntity);
ent_statObj.SetSceneID(objStore.worldID);
}
}
if (invItemObj)
{
invItemObj.RestoreInvItemID();
networkEntity = GetNetworkEntityDef(entNetwork, "Object_InventoryItem");
if(g_Game.CanCreateEntity( networkEntity )) //do not create network entities on clients
{
Object_InventoryItem ent_invItem = new Object_InventoryItem(invItemObj.GetItemID(), mat[0], mat[1], mat[2], mat[3], invItemObj.modelPath, invItemObj.remapPath, invItemObj.fxPath, invItemObj.modelMass, networkEntity);
ent_invItem.SetSceneID(invItemObj.worldID);
spd = VectorLength(invItemObj.worldAngVelocity) + VectorLength(invItemObj.worldVelocity);
if (spd > TKOMENTITY_MINVEL) {
dBodySetAngularVelocity(ent_invItem, invItemObj.worldAngVelocity);
SetVelocity(ent_invItem, invItemObj.worldVelocity);
} else
MPSafe_SetPhysicsObjectActive(ent_invItem, false);
invItemObj.LoadCustomScript(invItemObj.itemScript);
}
objects[n] = NULL; // Special for inventory item, remove from list to not delete it
}
if (dynObj)
{
networkEntity = GetNetworkEntityDef(entNetwork, "Object_Dynamic");
if(g_Game.CanCreateEntity( networkEntity )) //do not create network entities on clients
{
Object_Dynamic ent_dynObj = new Object_Dynamic(mat[0], mat[1], mat[2], mat[3], dynObj.fxPath, dynObj.modelPath, dynObj.remapPath, dynObj.modelMass, networkEntity);
ent_dynObj.SetSceneID(objStore.worldID);
spd = VectorLength(dynObj.worldAngVelocity) + VectorLength(dynObj.worldVelocity);
if (spd > TKOMENTITY_MINVEL) {
dBodySetAngularVelocity(ent_dynObj, dynObj.worldAngVelocity);
SetVelocity(ent_dynObj, dynObj.worldVelocity);
} else
MPSafe_SetPhysicsObjectActive(ent_dynObj, false);
}
}
if (projObj) {
networkEntity = GetNetworkEntityDef(entNetwork, "Projectile");
if(g_Game.CanCreateEntity( networkEntity )) //do not create network entities on clients
{
Projectile ent_projObj = new Projectile(mat[0], mat[1], mat[2], mat[3], ZeroVec, 0, projObj.fxPath, projObj.modelPath, projObj.ptcPath, projObj.modelMass, projObj.deathTime, projObj.deathOnImpact, networkEntity);
ent_projObj.SetSceneID(objStore.worldID);
spd = VectorLength(projObj.worldAngVelocity) + VectorLength(projObj.worldVelocity);
if (spd > TKOMENTITY_MINVEL) {
dBodySetAngularVelocity(ent_projObj, projObj.worldAngVelocity);
SetVelocity(ent_projObj, projObj.worldVelocity);
} else
MPSafe_SetPhysicsObjectActive(ent_projObj, false);
}
}
if (ptcObj) {
ParticleEmitter ent_ptcObj = PlayParticleEffect(ptcObj.ptcPath, mat, ptcObj.priority);
if (ent_ptcObj) {
ent_ptcObj.SetSceneID(objStore.worldID);
ent_ptcObj.PushFrame(ptcObj.ptcTime);
}
}
if (evFXObj) {
Event_FX ent_evFXObj = new Event_FX;
ent_evFXObj.SetSceneID(objStore.worldID);
SetMatrix(ent_evFXObj, mat);
ent_evFXObj.event_ptc = evFXObj.ptcPath;
ent_evFXObj.event_snd = evFXObj.sndPath;
}
if (evScptObj) {
Event_Script ent_evScptObj = new Event_Script;
ent_evScptObj.SetSceneID(objStore.worldID);
SetMatrix(ent_evScptObj, mat);
ent_evScptObj.event_scpt = evScptObj.scriptPath;
ent_evScptObj.LoadEventScript();
}
if (evTimObj) {
Event_Timer ent_evTimObj = new Event_Timer;
ent_evTimObj.SetSceneID(objStore.worldID);
SetMatrix(ent_evTimObj, mat);
if (evTimObj.CounterRunning)
ent_evTimObj.TriggerEvent();
ent_evTimObj.CounterRunning = evTimObj.CounterRunning;
ent_evTimObj.CounterCurrent = evTimObj.CounterCurrent;
ent_evTimObj.CounterTarget = evTimObj.CounterTarget;
ent_evTimObj.CounterRepeatsCurrent = evTimObj.CounterRepeatsCurrent;
ent_evTimObj.CounterRepeatsTotal = evTimObj.CounterRepeatsTotal;
ent_evTimObj.LinkEntIDs = evTimObj.LinkEntIDs;
}
if (trgObj) {
Trigger_Base ent_trigObj = NULL;
if (trgObj.trigOnStartType) ent_trigObj = new Trigger_OnStart;
else {
if (trgObj.trigOnExitType) ent_trigObj = new Trigger_OnExit;
else ent_trigObj = new Trigger_OnEnter;
}
if (ent_trigObj) {
ent_trigObj.SetSceneID(objStore.worldID);
SetOrigin(ent_trigObj, mat[3]);
ent_trigObj.radius = trgObj.radius;
ent_trigObj.height = trgObj.height;
ent_trigObj.trigger_vehicle = trgObj.trigVehicle;
ent_trigObj.trigger_projectile = trgObj.trigProjectile;
ent_trigObj.trigger_dynamic = trgObj.trigDynamic;
ent_trigObj.trigger_once = trgObj.trigOnce;
ent_trigObj.triggered = trgObj.triggered;
for (int lN = 0; lN < TRIGGER_MAXLINKS; lN++) {
ent_trigObj.linkIDs[lN] = trgObj.linkIDs[lN];
}
ent_trigObj.UpdateLinks();
}
}
}
}
ClearStoreObjects();
// Clean up any duplicate ID objects
for(n = 0; n < TKOM_EntityNum; n++)
{
TKOM_Entity scnEnt = TKOM_EntityList[n];
for(int i = n; i < TKOM_EntityNum; i++)
{
TKOM_Entity scnEnt2 = TKOM_EntityList[i];
if (scnEnt.GetID() > 0 && scnEnt != scnEnt2 && scnEnt.GetID() == scnEnt2.GetID()) {
Print(String("Duplicate ID found for TKOM_Entity ID: " + itoa(scnEnt.GetID()) + ", changing ID... Entity:"));
Print(scnEnt2);
scnEnt2.SetSceneID(TKOMHighestEntID + 1);
n = 0;
break;
}
}
}
}
//----------------------------------------------------------
void Location::ClearStoreObjects()
{
for(int n = 0; n < objectsCount; n++)
{
StoreObject_Base storeObj = objects[n];
if (storeObj)
delete storeObj;
objects[n] = NULL;
}
objectsCount = 0;
}
//----------------------------------------------------------
void Location::StoreBBlockGroups()
{
if (g_Game.IsClient())
return;
ClearStoredBBlockGroups();
for (int i = 0; i < Group_BuildingBlockListNum; i++)
{
Group_BuildingBlock grp_bblock = Group_BuildingBlockList[i];
if (grp_bblock)
{
BuildingBlockGroupObject storeGrp = new BuildingBlockGroupObject;
storeGrp.groupIndex = grp_bblock.groupIndex;
storeGrp.displayColor = grp_bblock.displayColor;
for (int n = 0; n < grp_bblock.blocks_num; n++)
{
Object_BuildingBlock bblock = grp_bblock.blocks[n];
storeGrp.blockIDs[n] = bblock.GetID();
}
storeGrp.blockIDs_num = grp_bblock.blocks_num;
bblockGroups[storeGrp.groupIndex] = storeGrp;
}
}
bblockGroupsCount = Group_BuildingBlockListNum;
}
//----------------------------------------------------------
void Location::RestoreBBlockGroups()
{
if (g_Game.IsClient())
return;
ClearBBlockGroups();
for(int i = 0; i < bblockGroupsCount; i++)
{
BuildingBlockGroupObject storeGrp = bblockGroups[i];
Group_BuildingBlock grp_bblock = new Group_BuildingBlock(false);
grp_bblock.groupIndex = storeGrp.groupIndex;
grp_bblock.displayColor = storeGrp.displayColor;
for (int n = 0; n < storeGrp.blockIDs_num; n++)
{
int bID = storeGrp.blockIDs[n];
Object_BuildingBlock bblock = (Object_BuildingBlock)FindEntityByID(g_Game.CurrentWorld, bID);
if (!bblock)
Print(String("LOCATION - RESTOREBBLOCKGROUPS: Could not find Object_BuildingBlock with ID: " + itoa(bID) + "!!!"));
grp_bblock.SetToGroup(bblock, n);
}
grp_bblock.blocks_num = storeGrp.blockIDs_num;
grp_bblock.RecalculateZones();
Group_BuildingBlockList[grp_bblock.groupIndex] = grp_bblock;
}
Group_BuildingBlockListNum = bblockGroupsCount;
ClearStoredBBlockGroups();
Print(String("LOCATION - RESTOREBBLOCKGROUPS: Restored " + itoa(Group_BuildingBlockListNum) + " groups..."));
}
//----------------------------------------------------------
void Location::ClearStoredBBlockGroups()
{
for(int n = 0; n < bblockGroupsCount; n++)
{
BuildingBlockGroupObject storeGrp = bblockGroups[n];
if (storeGrp)
delete storeGrp;
bblockGroups[n] = NULL;
}
bblockGroupsCount = 0;
}
//----------------------------------------------------------
void Location::RegenerateCompatibilityBBlockGroups()
{
if (g_Game.IsClient())
return;
// First unlink blocks' slots
Object_BuildingBlock buildBlock = (Object_BuildingBlock)GetNextEntity(NULL, Type("Object_BuildingBlock"));
while (buildBlock)
{
buildBlock.UnlinkSlots();
buildBlock = (Object_BuildingBlock)GetNextEntity(buildBlock, Type("Object_BuildingBlock"));
}
// Now re-link blocks' slots
buildBlock = (Object_BuildingBlock)GetNextEntity(NULL, Type("Object_BuildingBlock"));
while (buildBlock)
{
buildBlock.LinkToTouchingSlots();
buildBlock = (Object_BuildingBlock)GetNextEntity(buildBlock, Type("Object_BuildingBlock"));
}
// Finally, regenerate grouping
buildBlock = (Object_BuildingBlock)GetNextEntity(NULL, Type("Object_BuildingBlock"));
while (buildBlock)
{
if (buildBlock.IsDynamic)
BBlockUpdateGroupingForBlock(buildBlock, false);
else
BBlockUpdateGroupingForBlock(buildBlock, true);
buildBlock = (Object_BuildingBlock)GetNextEntity(buildBlock, Type("Object_BuildingBlock"));
}
}
//----------------------------------------------------------
void Location::DoAnalysis(TKOM_Entity vehicle, string instSubType, int physMat, string specMat, vector pos)
{
for(local int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget target = scienceTargets[n];
target.DoAnalysis(vehicle, instSubType, physMat, specMat, pos);
}
}
//----------------------------------------------------------
void Location::DoPhoto(TKOM_Entity vehicle, int camNum, vector camPos, bool color)
{
for(local int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget target = scienceTargets[n];
target.DoPhoto(vehicle, camNum, camPos, color);
}
}
//----------------------------------------------------------
ScienceTarget Location::FindScienceTarget(string name, bool recursive)
{
for(local int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget target = scienceTargets[n];
if(target.name == name)
return scienceTargets[n];
if(recursive)
{
ScienceTarget child = target.FindChildTarget(name, recursive);
if(child)
return child;
}
}
return NULL;
}
//----------------------------------------------------------
ScienceTarget Location::FindScienceTargetDuplicate(string name, bool recursive, int dupNum)
{
gDuplicateSearch = 0;
for(local int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget target = scienceTargets[n];
if(target.name == name) {
gDuplicateSearch++;
if (gDuplicateSearch == dupNum)
return scienceTargets[n];
}
if(recursive)
{
ScienceTarget child = target.FindChildTargetDuplicate(name, recursive, dupNum);
if(child)
return child;
}
}
return NULL;
}
//----------------------------------------------------------
void Location::AddScienceTarget(ScienceTarget target)
{
if(!target)
return;
if(target.parent)
target.parent.RegisterChildTarget(target);
else
{
scienceTargets[scienceTargetsCount] = target;
scienceTargetsCount++;
}
}
//----------------------------------------------------------
bool Location::RemoveScienceTarget(ScienceTarget target)
{
if(!target)
return false;
local int i;
int remSlot = -1;
for (i = 0; i < MAX_SCIENCE_TARGETS_PER_LOCATION; i++) {
if (scienceTargets[i] == target) {
scienceTargets[i] = NULL;
remSlot = i;
i = MAX_SCIENCE_TARGETS_PER_LOCATION;
}
}
if (remSlot != -1) {
for (i = MAX_SCIENCE_TARGETS_PER_LOCATION - 1; i >= remSlot; i--) {
if (scienceTargets[i] != NULL) {
scienceTargets[remSlot] = scienceTargets[i];
scienceTargets[i] = NULL;
remSlot = i;
i = 0;
}
}
scienceTargetsCount--;
return true;
} else
return false;
}
//----------------------------------------------------------
void Location::RemoveOnCompST(string onCompST)
{
for(local int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget target = scienceTargets[n];
target.RemoveOnCompST(onCompST);
}
}
//----------------------------------------------------------
void Location::UpdateWorldSTZones()
{
for(local int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget target = scienceTargets[n];
target.UpdateWorldSTZones();
}
}
//----------------------------------------------------------
void Location::UpdateSTVisualizers(bool show_sts, bool show_lnk)
{
// Tell all of our Science targets to update their link markers
for (local int i = 0; i < scienceTargetsCount; i++) {
if (scienceTargets[i]) {
ScienceTarget child = scienceTargets[i];
child.UpdateSTVisualizers(show_sts, show_lnk, this);
}
}
}
//----------------------------------------------------------
ScienceTarget Location::CreateGenericScienceTarget(ScienceTarget parent, string name, Location loc)
{
ScienceTarget target = new ScienceTarget();
target.owner = loc;
target.parent = parent;
target.name = name;
AddScienceTarget(target);
return target;
}
//----------------------------------------------------------
ScienceTargetPhoto Location::CreatePhotoScienceTarget(ScienceTarget parent, string name, Location loc)
{
ScienceTargetPhoto target = new ScienceTargetPhoto();
target.owner = loc;
target.parent = parent;
target.name = name;
AddScienceTarget(target);
return target;
}
//----------------------------------------------------------
ScienceTargetAnalyze Location::CreateAnalyzeScienceTarget(ScienceTarget parent, string name, Location loc)
{
ScienceTargetAnalyze target = new ScienceTargetAnalyze();
target.owner = loc;
target.parent = parent;
target.name = name;
AddScienceTarget(target);
return target;
}
//----------------------------------------------------------
ScienceTarget Location::CreateScienceTargetByTypeID(string typeID, ScienceTarget parent, string name, Location loc)
{
if(typeID == "$ExploreTarget")
return CreateGenericScienceTarget(parent, name, loc);
else
{
if(typeID == "$AnalyzeTarget")
return CreateAnalyzeScienceTarget(parent, name, loc);
else
{
if(typeID == "$PhotoTarget")
return CreatePhotoScienceTarget(parent, name, loc);
}
}
return NULL;
}
//----------------------------------------------------------
STargetZone Location::CreateScienceTargetZone(ScienceTarget owner)
{
if(!owner)
return NULL;
return owner.CreateZone();
}
//----------------------------------------------------------
void Location::DestroyScienceTargets()
{
for(int n = scienceTargetsCount - 1; n >= 0; n--)
{
ScienceTarget target = scienceTargets[n];
if(target)
{
delete target;
target = NULL;
}
scienceTargets[n] = NULL;
}
scienceTargetsCount = 0;
}
//----------------------------------------------------------
int Location::ConvertPriority(string str)
{
int result = ST_P_INVALID;
for (int i = 1; i < sizeof(ST_PRIORITIES); i++) {
if (str == ST_PRIORITIES[i]) {
result = i;
break;
}
}
return result;
}
//----------------------------------------------------------
bool ScienceTarget::IsGlobalObjectiveAssigned(string globalObj)
{
if (parent == NULL) {
string globObjList[GLOBOBJ_MAXTOTALITEMS];
int numTokens = ParseString(mission_globalObjectives, globObjList);
for (int i = 0; i < numTokens; i++) {
if (globObjList[i] == globalObj)
return true;
}
}
return false;
}
//----------------------------------------------------------
float ScienceTarget::GetGlobalObjectiveInstrumentRating(InstrumentDef inst)
{
local float result = 0;
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if(child) {
float tmpResult = child.GetGlobalObjectiveInstrumentRating(inst);
if (tmpResult > result)
result = tmpResult;
}
}
return result;
}
//----------------------------------------------------------
float ScienceTargetAnalyze::GetGlobalObjectiveInstrumentRating(InstrumentDef inst)
{
local float result = 0;
if (priority == ST_P_MAJOR && GetCompletion() < 1 && specInst != "" && !HasTechForTarget(false, ST_P_MAJOR, false)) {
string tokens[MAX_SCIENCE_TARGET_ANZ_SPECINST];
int numTokens = ParseString(specInst, tokens);
for (int i = 0; i < numTokens; i++) {
if (tokens[i] == inst.codeName) {
result = fsum(1 / numTokens);
}
}
}
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if(child) {
float tmpResult = child.GetGlobalObjectiveInstrumentRating(inst);
if (tmpResult > result)
result = tmpResult;
}
}
return result;
}
//----------------------------------------------------------
bool ScienceTarget::IsGlobalObjectiveColorCamRequired()
{
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if (child && child.IsGlobalObjectiveColorCamRequired())
return true;
}
return false;
}
//----------------------------------------------------------
bool ScienceTargetPhoto::IsGlobalObjectiveColorCamRequired()
{
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if (child && child.IsGlobalObjectiveColorCamRequired())
return true;
}
if (priority == ST_P_MAJOR && GetCompletion() < 1 && colorCameraReq)
return true;
else
return false;
}
//----------------------------------------------------------
void ScienceTarget::ReCallSTOnComp(Location curLoc)
{
if (GetCompletion() >= 1)
EnableOnCompSTs(curLoc);
for(local int n = 0; n < childTargetsCount; n++)
{
local ScienceTarget child = childTargets[n];
if(child)
child.ReCallSTOnComp(curLoc);
}
}
//----------------------------------------------------------
void Location::ReCallSTOnComp()
{
for(local int n = 0; n < scienceTargetsCount; n++)
{
local ScienceTarget child = scienceTargets[n];
if(child)
child.ReCallSTOnComp(this);
}
}
//----------------------------------------------------------
void Location::ReadSCNSTs(tparse file, bool checkForPrev)
{
const int maxTokens = 64;
string tokens[maxTokens];
int line = 0;
ScienceTarget levels[MAX_SCIENCE_TARGET_NESTING];
int curLevel = 0;
int parentLevel = -1;
levels[curLevel] = NULL;
STargetZone curZone = NULL;
int curZoneNum = 0;
string usedIDsList = "";
// Parse through and extract science target data
int numTokens = ParseLine(file, line, tokens);
while(numTokens > 0)
{
ScienceTarget curTarget = levels[curLevel];
ScienceTargetAnalyze analyzeTarget = NULL;
ScienceTargetPhoto photoTarget = NULL;
if(curTarget)
{
if(curTarget.IsAnalyzeType())
analyzeTarget = (ScienceTargetAnalyze)curTarget;
if(curTarget.IsPhotoType())
photoTarget = (ScienceTargetPhoto)curTarget;
}
string firstToken = tokens[0];
switch(firstToken)
{
case "$ExploreTarget":
{
curLevel = 0;
parentLevel = -1;
curZone = NULL;
curZoneNum = 0;
// Check usage number of ST ID
if (usedIDsList != "") usedIDsList += " ";
usedIDsList += tostr(34) + tokens[1] + tostr(34);
if (GetNumStrInStringList(tokens[1], usedIDsList) > 1) // Used more than once, so give warning
Print(String("WARNING! ST ID '" + tokens[1] + "' used more than once in " + name + "!!!"));
if (checkForPrev && FindScienceTarget(tokens[1], true))
curTarget = FindScienceTarget(tokens[1], true);
else {
curTarget = CreateScienceTargetByTypeID(firstToken, NULL, tokens[1], this);
curTarget.GenerateDefaultMissionData();
}
levels[curLevel] = curTarget;
curTarget = NULL;
break;
}
case "$AnalyzeTarget":
{
curLevel = 0;
parentLevel = -1;
curZone = NULL;
curZoneNum = 0;
// Check usage number of ST ID
if (usedIDsList != "") usedIDsList += " ";
usedIDsList += tostr(34) + tokens[1] + tostr(34);
if (GetNumStrInStringList(tokens[1], usedIDsList) > 1) // Used more than once, so give warning
Print(String("WARNING! ST ID '" + tokens[1] + "' used more than once in " + name + "!!!"));
if (checkForPrev && FindScienceTarget(tokens[1], true))
curTarget = FindScienceTarget(tokens[1], true);
else {
curTarget = CreateScienceTargetByTypeID(firstToken, NULL, tokens[1], this);
curTarget.GenerateDefaultMissionData();
}
levels[curLevel] = curTarget;
curTarget = NULL;
break;
}
case "$PhotoTarget":
{
curLevel = 0;
parentLevel = -1;
curZone = NULL;
curZoneNum = 0;
// Check usage number of ST ID
if (usedIDsList != "") usedIDsList += " ";
usedIDsList += tostr(34) + tokens[1] + tostr(34);
if (GetNumStrInStringList(tokens[1], usedIDsList) > 1) // Used more than once, so give warning
Print(String("WARNING! ST ID '" + tokens[1] + "' used more than once in " + name + "!!!"));
if (checkForPrev && FindScienceTarget(tokens[1], true))
curTarget = FindScienceTarget(tokens[1], true);
else {
curTarget = CreateScienceTargetByTypeID(firstToken, NULL, tokens[1], this);
curTarget.GenerateDefaultMissionData();
}
levels[curLevel] = curTarget;
curTarget = NULL;
break;
}
case "++":
{
int nextLevel = 1;
for(int n = 1; n < numTokens; n++)
{
if(tokens[n] == "++")
nextLevel++;
}
string nextToken = tokens[nextLevel];
if(nextToken == "$ExploreTarget" || nextToken == "$AnalyzeTarget" || nextToken == "$PhotoTarget")
{
if(nextLevel != curLevel)
{
curLevel = nextLevel;
parentLevel = curLevel - 1;
}
curZone = NULL;
curZoneNum = 0;
// Check usage number of ST ID
if (usedIDsList != "") usedIDsList += " ";
usedIDsList += tostr(34) + tokens[nextLevel + 1] + tostr(34);
if (GetNumStrInStringList(tokens[nextLevel + 1], usedIDsList) > 1) // Used more than once, so give warning
Print(String("WARNING! ST ID '" + tokens[nextLevel + 1] + "' used more than once in " + name + "!!!"));
if (checkForPrev && FindScienceTarget(tokens[nextLevel + 1], true))
levels[curLevel] = FindScienceTarget(tokens[nextLevel + 1], true);
else
levels[curLevel] = CreateScienceTargetByTypeID(nextToken, levels[parentLevel], tokens[nextLevel + 1], this);
}
break;
}
case "$Zone":
{
if(curTarget)
{
if (checkForPrev && curTarget.zones[curZoneNum])
curZone = curTarget.zones[curZoneNum];
else
curZone = CreateScienceTargetZone(curTarget);
curZone.coords = String2Vector(tokens[1]);
curZone.radius = atof(tokens[2]);
curZone.height = atof(tokens[3]);
curZoneNum++;
}
break;
}
case "Title":
{
if(curTarget)
curTarget.title = tokens[1];
break;
}
case "Description":
{
if(curTarget)
curTarget.description = tokens[1];
break;
}
case "Priority":
{
if(curTarget)
curTarget.priority = ConvertPriority(tokens[1]);
break;
}
case "Worth":
{
if(curTarget)
curTarget.worth = atoi(tokens[1]);
break;
}
case "Enabled":
{
if(curTarget)
curTarget.enabled = (bool)atoi(tokens[1]);
break;
}
case "OnComplEnable":
{
if(curTarget)
curTarget.AddOnComp(tokens[1]);
break;
}
case "PhysMat":
{
if(analyzeTarget)
analyzeTarget.physMat = GetPhysMaterialIndex(tokens[1]);
break;
}
case "SpecMat":
{
if(analyzeTarget)
analyzeTarget.specMat = tokens[1];
break;
}
case "SpecInst":
{
if(analyzeTarget)
analyzeTarget.specInst = tokens[1];
break;
}
case "MinIncNum":
{
if(photoTarget)
photoTarget.minIncNum = atoi(tokens[1]);
break;
}
case "ColorCameraReq":
{
if(photoTarget)
photoTarget.colorCameraReq = (bool)atoi(tokens[1]);
break;
}
// Mission params
case "Mission_Title":
{
if(curTarget)
curTarget.mission_title = tokens[1];
break;
}
case "Mission_Description":
{
if(curTarget)
curTarget.mission_description = tokens[1];
break;
}
case "Mission_Result":
{
if(curTarget)
curTarget.mission_result = tokens[1];
break;
}
case "Mission_GlobalObjectives":
{
if(curTarget)
curTarget.mission_globalObjectives = tokens[1];
break;
}
case "Mission_Priority":
{
if(curTarget)
curTarget.mission_priority = ConvertPriority(tokens[1]);
break;
}
case "Mission_WorthMajor":
{
if(curTarget)
curTarget.mission_worth_major = atoi(tokens[1]);
break;
}
case "Mission_WorthMinor":
{
if(curTarget)
curTarget.mission_worth_minor = atoi(tokens[1]);
break;
}
case "Mission_MobilityReq":
{
if(curTarget)
curTarget.mission_mobilityRequired = (bool)atoi(tokens[1]);
break;
}
}
for (int i = 0; i < maxTokens; i++)
{
tokens[i] = "";
}
numTokens = ParseLine(file, ++line, tokens);
}
EndParse(file);
if (checkForPrev)
ReCallSTOnComp(); // If synchronizing STs, re-call any OnComplete events
}
//----------------------------------------------------------
bool Location::GetScienceTargetsFromSCN(string fileName, bool checkForPrevious)
{
if (!checkForPrevious)
DestroyScienceTargets();
tparse file = BeginParse(fileName);
if(!file) {
Print(String("VALIDATE LOCATIONS: Could not locate scenario file " + fileName + ", ignoring..."));
return false;
} else
ReadSCNSTs(file, checkForPrevious);
return true;
}
//----------------------------------------------------------
void Location::WriteScienceTargetsToSCN(int file, local int level)
{
if (scienceTargetsCount > 0) {
FPrintln(file, "SCIENCETARGETS");
for (local int i = 0; i < scienceTargetsCount; i++) {
ScienceTarget stEnt = scienceTargets[i];
stEnt.WriteScienceTargetsToSCN(file, level);
}
}
}
//----------------------------------------------------------
void Location::SetWorldParameters()
{
Location_LongLat = Vector(longitude, latitude, 0);
dSetGravity(g_Game.CurrentWorld, loc_gravity);
UpdateColliderInteractionLayers(g_Game.CurrentWorld);
CurrentWorldGravity = loc_gravity;
CurrentWorldAirFriction = loc_airfriction;
if (loc_skypreset != "") {
InitSky(loc_skypreset);
VSkyPreset = loc_skypreset;
}
}
//----------------------------------------------------------
void Location::SetEditorUTC()
{
if (loc_editorUTC_DMY != ZeroVec && g_Campaign) {
g_Campaign.SetRealTime(false);
g_Campaign.SimUTC_year = floor(loc_editorUTC_DMY[2]);
g_Campaign.SimUTC_month = floor(loc_editorUTC_DMY[1]);
g_Campaign.SimUTC_day = floor(loc_editorUTC_DMY[0]);
g_Campaign.SimUTC_hour = floor(loc_editorUTC_HMS[0]);
g_Campaign.SimUTC_minute = floor(loc_editorUTC_HMS[1]);
g_Campaign.SimUTC_second = floor(loc_editorUTC_HMS[2]);
}
}
//----------------------------------------------------------
void Location::AddDefaultResources()
{
const int maxRscTokens = 5;
string rscTokens[maxRscTokens];
string resFileName;
int resFileAttribute;
// First search internal folders
FindFileHandle resff = FindFile(FILEPATH_INT_CFGLIST_RESOURCES + "*.cfglist", resFileName, resFileAttribute, 0);
if(resff)
{
while(true)
{
tparse resFile = BeginParse(FILEPATH_INT_CFGLIST_RESOURCES + resFileName);
if (resFile)
{
int resLineNum = 0;
int resTokenNum = maxRscTokens;
while (resTokenNum > 0)
{
resTokenNum = ParseLine(resFile, resLineNum, rscTokens);
if (resTokenNum > 0 && rscTokens[0] != "")
{
string resType = rscTokens[2];
if (FindResourceByName(rscTokens[0]))
{
resLineNum++;
continue;
}
if (resType == "GROUND")
AddResourceType(rscTokens[0], rscTokens[3], rscTokens[4], 0, 0, String2Vector(rscTokens[1]), RESOURCE_AREATYPE_GROUND);
if (resType == "SURFACE")
AddResourceType(rscTokens[0], rscTokens[3], rscTokens[4], 0, 0, String2Vector(rscTokens[1]), RESOURCE_AREATYPE_SURFACE);
if (resType == "ATMOSPHERIC")
AddResourceType(rscTokens[0], rscTokens[3], rscTokens[4], 0, 0, String2Vector(rscTokens[1]), RESOURCE_AREATYPE_ATMOSPHERIC);
}
resLineNum++;
}
EndParse(resFile);
}
if(!FindNextFile(resff, resFileName, resFileAttribute))
break;
}
CloseFindFile(resff);
}
// Now go through addons
string resaddons[ADDONSMAX];
int resaddonsCount = GetAddons(resaddons);
for(int addN = 0; addN < resaddonsCount; addN++)
{
string resaddonName = resaddons[addN];
// Only search the addon if it is enabled via the Addons menu
if(g_Game.IsAddonActive(resaddonName) == false)
continue;
resff = FindFile("$" + resaddonName + ":" + FILEPATH_ADDONS_CFGLIST_RESOURCES + "*.cfglist", resFileName, resFileAttribute, 0);
if(resff)
{
while(true)
{
resFile = BeginParse("$" + resaddonName + ":" + FILEPATH_ADDONS_CFGLIST_RESOURCES + resFileName);
if (resFile)
{
resLineNum = 0;
resTokenNum = maxRscTokens;
while (resTokenNum > 0)
{
resTokenNum = ParseLine(resFile, resLineNum, rscTokens);
if (resTokenNum > 0 && rscTokens[0] != "")
{
resType = rscTokens[2];
if (FindResourceByName(rscTokens[0]))
{
resLineNum++;
continue;
}
if (resType == "GROUND")
AddResourceType(rscTokens[0], rscTokens[3], rscTokens[4], 0, 0, String2Vector(rscTokens[1]), RESOURCE_AREATYPE_GROUND);
if (resType == "SURFACE")
AddResourceType(rscTokens[0], rscTokens[3], rscTokens[4], 0, 0, String2Vector(rscTokens[1]), RESOURCE_AREATYPE_SURFACE);
if (resType == "ATMOSPHERIC")
AddResourceType(rscTokens[0], rscTokens[3], rscTokens[4], 0, 0, String2Vector(rscTokens[1]), RESOURCE_AREATYPE_ATMOSPHERIC);
}
resLineNum++;
}
EndParse(resFile);
}
if(!FindNextFile(resff, resFileName, resFileAttribute))
break;
}
CloseFindFile(resff);
}
}
}
//----------------------------------------------------------
bool Location::Load(string fileName, bool reloading)
{
local tparse file = BeginParse(fileName);
if(!file)
{
Print(String("VALIDATE LOCATIONS: Could not locate file " + fileName + ", ignoring..."));
return false;
}
const int maxTokens = 64;
string tokens[maxTokens];
// Now load location data
string resources_name[RESOURCE_MAXTYPES];
string resources_title[RESOURCE_MAXTYPES];
string resources_desc[RESOURCE_MAXTYPES];
int resources_amountMaxTotal[RESOURCE_MAXTYPES];
float resources_distributionClumping[RESOURCE_MAXTYPES];
vector resources_displayColor[RESOURCE_MAXTYPES];
int resources_areaType[RESOURCE_MAXTYPES];
int resourcesNum = 0;
for (local int i = 0; i < RESOURCE_MAXTYPES; i++)
{
resources_name[i] = "";
resources_title[i] = "";
resources_desc[i] = "";
resources_amountMaxTotal[i] = 0;
resources_distributionClumping[i] = 0;
resources_displayColor[i] = ZeroVec;
resources_areaType[i] = RESOURCE_AREATYPE_GROUND;
}
bool hideLoc = false;
// Location file exists, so parse through it
int line = 0;
int numTokens = ParseLine(file, line, tokens);
while(numTokens > 0)
{
string firstToken = tokens[0];
switch(firstToken)
{
case "$Location":
{
break;
}
case "Hidden":
{
if (tokens[1] == "true")
hideLoc = true;
break;
}
case "Longitude":
{
longitude = atof(tokens[1]);
break;
}
case "Latitude":
{
latitude = atof(tokens[1]);
break;
}
case "BodyCenterDist":
{
bodyCenterDist = atof(tokens[1]);
break;
}
case "ReentryVelocity":
{
loc_reentryVel = String2Vector(tokens[1]);
break;
}
case "ReentryOffsetPosition":
{
loc_reentryOffsetPos = String2Vector(tokens[1]);
break;
}
case "ReentryOffsetAngles":
{
loc_reentryOffsetAng = String2Vector(tokens[1]);
break;
}
case "Gravity":
{
loc_gravity = String2Vector(tokens[1]);
break;
}
case "AirFriction":
{
loc_airfriction = atof(tokens[1]);
break;
}
case "EditorUTC_DMY":
{
loc_editorUTC_DMY = String2Vector(tokens[1]);
break;
}
case "EditorUTC_HMS":
{
loc_editorUTC_HMS = String2Vector(tokens[1]);
break;
}
case "SkyPreset":
{
loc_skypreset = tokens[1];
break;
}
case "Title":
{
loc_title = tokens[1];
break;
}
case "Description":
{
loc_desc = tokens[1];
break;
}
case "PrevImage":
{
loc_prev_image = tokens[1];
break;
}
case "MapImage":
{
loc_map_image = tokens[1];
break;
}
case "UnlockCost":
{
unlockCost = atoi(tokens[1]);
if (unlockCost > 0 && !reloading)
locked = true;
break;
}
case "Body":
{
loc_body = tokens[1];
break;
}
case "ParentBody":
{
loc_parentbody = tokens[1];
break;
}
case "WorldBounds":
{
loc_worldbounds = String2Vector(tokens[1]);
break;
}
case "WorldSize":
{
loc_worldsize[0] = atof(tokens[1]);
loc_worldsize[1] = atof(tokens[2]);
break;
}
case "SectorSize":
{
loc_sectorSize = atof(tokens[1]);
break;
}
case "Resource":
{
if (resourcesNum < RESOURCE_MAXTYPES)
{
resources_name[resourcesNum] = tokens[1];
resources_amountMaxTotal[resourcesNum] = atoi(tokens[2]);
resources_distributionClumping[resourcesNum] = atof(tokens[3]);
resources_displayColor[resourcesNum] = String2Vector(tokens[4]);
string rscAreaType = tokens[5];
strupper(rscAreaType);
if (rscAreaType == "GROUND") resources_areaType[resourcesNum] = RESOURCE_AREATYPE_GROUND;
if (rscAreaType == "SURFACE") resources_areaType[resourcesNum] = RESOURCE_AREATYPE_SURFACE;
if (rscAreaType == "ATMOSPHERIC") resources_areaType[resourcesNum] = RESOURCE_AREATYPE_ATMOSPHERIC;
resources_title[resourcesNum] = tokens[6];
resources_desc[resourcesNum] = tokens[7];
resourcesNum++;
}
else
Print(String(fileName + ": Could not add resource '" + tokens[1] + "', max resource types reached!"));
break;
}
}
for (i = 0; i < maxTokens; i++)
{
tokens[i] = "";
}
numTokens = ParseLine(file, ++line, tokens);
}
EndParse(file);
if (hideLoc)
Hide(true);
CalculateResourceSectorNums();
for (i = 0; i < resourcesNum; i++)
{
AddResourceType(resources_name[i], resources_title[i], resources_desc[i], resources_amountMaxTotal[i], resources_distributionClumping[i], resources_displayColor[i], resources_areaType[i]);
resources_name[i] = "";
resources_title[i] = "";
resources_desc[i] = "";
resources_amountMaxTotal[i] = 0;
resources_distributionClumping[i] = 0;
resources_displayColor[i] = ZeroVec;
resources_areaType[i] = RESOURCE_AREATYPE_GROUND;
}
if (!g_Game.IsClient())
DistributeResources();
// Add default resources
AddDefaultResources();
return true;
}
//----------------------------------------------------------
void Location::PrintData()
{
Print("=========================================");
Print(String("Location: " + name));
Print(longitude);
Print(latitude);
}
//----------------------------------------------------------
string Location::GetEntFilePath()
{
return loc_path;
}
//----------------------------------------------------------
string Location::GetLocFilePath()
{
int len = strlen(loc_path);
if(len <= 4)
return "";
return substr(loc_path, 0, len - 4) + ".loc";
}
//----------------------------------------------------------
// Sets the resource type at the sector and surrounding sectors as discovered
void Location::DiscoverResourceAtSector(int resType, int sectorX, int sectorY, float sectorRadius, bool notify)
{
int discoveredNew = -1;
if (sectorRadius > 0) // Multiple sectors
{
vector centerPos = Vector(sectorX, sectorY, 0);
for (int x = 0; x < ResourcesSectorNum_X; x++)
{
for (int y = 0; y < ResourcesSectorNum_Y; y++)
{
vector sectorPos = Vector(x, y, 0);
if (VectorLength(sectorPos - centerPos) > sectorRadius)
continue;
switch(resType)
{
case RESOURCE_AREATYPE_GROUND:
{
if (!ResourceDiscovered_Ground[x][y])
discoveredNew = RESOURCE_AREATYPE_GROUND;
ResourceDiscovered_Ground[x][y] = true;
break;
}
case RESOURCE_AREATYPE_SURFACE:
{
if (!ResourceDiscovered_Surface[x][y])
discoveredNew = RESOURCE_AREATYPE_SURFACE;
ResourceDiscovered_Surface[x][y] = true;
break;
}
case RESOURCE_AREATYPE_ATMOSPHERIC:
{
if (!ResourceDiscovered_Atmospheric[x][y])
discoveredNew = RESOURCE_AREATYPE_ATMOSPHERIC;
ResourceDiscovered_Atmospheric[x][y] = true;
break;
}
}
}
}
}
else // Single sector
{
switch(resType)
{
case RESOURCE_AREATYPE_GROUND:
{
if (!ResourceDiscovered_Ground[sectorX][sectorY])
discoveredNew = RESOURCE_AREATYPE_GROUND;
ResourceDiscovered_Ground[sectorX][sectorY] = true;
break;
}
case RESOURCE_AREATYPE_SURFACE:
{
if (!ResourceDiscovered_Surface[sectorX][sectorY])
discoveredNew = RESOURCE_AREATYPE_SURFACE;
ResourceDiscovered_Surface[sectorX][sectorY] = true;
break;
}
case RESOURCE_AREATYPE_ATMOSPHERIC:
{
if (!ResourceDiscovered_Atmospheric[sectorX][sectorY])
discoveredNew = RESOURCE_AREATYPE_ATMOSPHERIC;
ResourceDiscovered_Atmospheric[sectorX][sectorY] = true;
break;
}
}
}
if (notify)
{
string title = "Resource prospecting of Sector x" + itoa(sectorX) + " y" + itoa(sectorY) + " complete!"
if (discoveredNew == RESOURCE_AREATYPE_GROUND)
g_Campaign.AddNotification("gui/layouts/tkom_item_notification_res_sub.layout", title, "", "");
if (discoveredNew == RESOURCE_AREATYPE_SURFACE)
g_Campaign.AddNotification("gui/layouts/tkom_item_notification_res_soil.layout", title, "", "");
if (discoveredNew == RESOURCE_AREATYPE_ATMOSPHERIC)
g_Campaign.AddNotification("gui/layouts/tkom_item_notification_res_air.layout", title, "", "");
}
}
//----------------------------------------------------------
ScienceTarget Location::GetFirstEnabledMission()
{
for(int n = 0; n < scienceTargetsCount; n++)
{
ScienceTarget mis = scienceTargets[n];
if(mis.enabled)
return mis;
}
return NULL;
}
//----------------------------------------------------------
// Returns the forecasted weather for an hour ahead
float Location::WeatherGetHourForecast()
{
float result = loc_weatherForecast[1];
return result;
}
//----------------------------------------------------------
// Returns the overall bias of the forecast weather for the input number of hours ahead
float Location::WeatherGetForecastBias(int numHours)
{
clamp numHours<1, MAX_WEATHERFORECAST_HOURS>;
float result = 0;
for(int n = 0; n < numHours; n++)
{
result += loc_weatherForecast[n];
}
result = result * fsum(1 / numHours);
clamp result<0, 1>;
return result;
}
//----------------------------------------------------------
// Generates a weather forecast for the next numHours number of hours
void Location::WeatherGenerateForecast(int numHours, bool completeRefresh, bool editorMode, float weatherBias)
{
int n;
float lastWeatherVal, tgtWeather;
loc_weatherForecast_currentHour = 0;
// First move values down
if (!completeRefresh) {
for(n = 0; n < MAX_WEATHERFORECAST_HOURS - numHours; n++)
{
if (sum(n + numHours) >= MAX_WEATHERFORECAST_HOURS)
break;
loc_weatherForecast[n] = loc_weatherForecast[n + numHours];
}
lastWeatherVal = loc_weatherVal;
for(n = MAX_WEATHERFORECAST_HOURS - numHours; n < MAX_WEATHERFORECAST_HOURS; n++)
{
tgtWeather = lastWeatherVal;
if (weatherBias == -1) {
if (frand(0, 1) < 0.25)
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, 0);
else
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, MAX_WEATHERFORECAST_MAXHOURLYCHANGE);
} else {
if (frand(0, 1) < 0.3)
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, MAX_WEATHERFORECAST_MAXHOURLYCHANGE);
else {
if (tgtWeather < weatherBias)
tgtWeather += frand(0, MAX_WEATHERFORECAST_MAXHOURLYCHANGE);
else
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, 0);
}
}
clamp tgtWeather<0, 1>;
loc_weatherForecast[n] = tgtWeather;
lastWeatherVal = tgtWeather;
}
loc_weatherVal = loc_weatherForecast[0];
} else {
if (editorMode)
loc_weatherVal = 0;
else {
if (frand(0, 1) < 0.75)
loc_weatherVal = frand(0, 0.25);
else {
if (frand(0, 1) < 0.75)
loc_weatherVal = frand(0, 0.5);
else {
if (frand(0, 1) < 0.5)
loc_weatherVal = frand(0, 0.7);
else
loc_weatherVal = frand(0, 1);
}
}
}
lastWeatherVal = loc_weatherVal;
for(n = 0; n < MAX_WEATHERFORECAST_HOURS; n++)
{
if (editorMode)
loc_weatherForecast[n] = 0;
else {
tgtWeather = lastWeatherVal;
if (weatherBias == -1) {
if (frand(0, 1) < 0.25)
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, 0);
else
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, MAX_WEATHERFORECAST_MAXHOURLYCHANGE);
} else {
if (frand(0, 1) < 0.3)
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, MAX_WEATHERFORECAST_MAXHOURLYCHANGE);
else {
if (tgtWeather < weatherBias)
tgtWeather += frand(0, MAX_WEATHERFORECAST_MAXHOURLYCHANGE);
else
tgtWeather += frand(-MAX_WEATHERFORECAST_MAXHOURLYCHANGE, 0);
}
}
clamp tgtWeather<0, 1>;
loc_weatherForecast[n] = tgtWeather;
lastWeatherVal = tgtWeather;
}
}
}
UpdateBadWeatherNotifications();
}
//----------------------------------------------------------
// Update weather in the location
void Location::WeatherUpdate(float fTimeSlice)
{
loc_weatherForecast_currentHour += fTimeSlice / 60 / 60;
if (loc_weatherForecast_currentHour >= 1)
WeatherGenerateForecast(1, false, false, -1);
loc_weatherVal = loc_weatherForecast[1] - loc_weatherForecast[0] * loc_weatherForecast_currentHour + loc_weatherForecast[0];
float customWeather = -1;
float customWeatherLerp = 1;
if (g_Mission)
{
customWeather = g_Mission.GetCustomWeatherValue();
customWeatherLerp = g_Mission.GetCustomWeatherLerp();
}
if (customWeather >= 0)
{
loc_weatherVal *= 1 - customWeatherLerp;
loc_weatherVal += customWeather * customWeatherLerp;
}
clamp loc_weatherVal<0, 1>;
}
//----------------------------------------------------------
// Skip numHours amount of hours
void Location::WeatherSkip(int numHours)
{
if (g_Campaign && g_Campaign.campaignIndex != CAMPAIGN_SPACE_PROGRAM && g_Campaign.campaignIndex != CAMPAIGN_SCENARIOS)
WeatherGenerateForecast(numHours, true, true, -1);
else {
if (numHours > MAX_WEATHERFORECAST_HOURS)
WeatherGenerateForecast(numHours, true, false, -1);
else
WeatherGenerateForecast(numHours, false, false, -1);
}
}
//----------------------------------------------------------
// Returns whether the weather values are null
bool Location::WeatherIsNull()
{
float totalWeatherValue = 0;
for(int n = 0; n < MAX_WEATHERFORECAST_HOURS; n++)
{
totalWeatherValue += loc_weatherForecast[n];
}
if (totalWeatherValue == 0)
return true;
else
return false;
}
//----------------------------------------------------------
// Handles displaying of bad weather notifications
void Location::UpdateBadWeatherNotifications()
{
if (loc_title == "" || vehiclesCount == 0 || !g_Campaign.Rover_SetTimeType)
return;
string emptyListStr[2] = {"", ""};
int i;
for(i = 0; i < 12; i++)
{
float weatherValue = loc_weatherForecast[i];
if (weatherValue >= 0.7) {
int year, month, day, hour, minute, second;
if (g_Campaign.Rover_RealUTC) {
GetYearMonthDayUTC(year, month, day);
GetHourMinuteSecondUTC(hour, minute, second);
} else {
year = g_Campaign.SimUTC_year;
month = g_Campaign.SimUTC_month;
day = g_Campaign.SimUTC_day;
hour = g_Campaign.SimUTC_hour;
minute = g_Campaign.SimUTC_minute;
second = g_Campaign.SimUTC_second;
}
string timeStamp = DateToString(Vector(day, month, year)) + " - " + TimeToString(Vector(hour, minute, second)) + " UTC";
if (i > 0)
g_Campaign.AddNotification("gui/layouts/tkom_item_notification_weather.layout", "#tkom_weather_title", "#tkom_weather_desc_loc|#tkom_weather_desc_haz|#tkom_weather_desc_time|#tkom_weather_desc_timestamp", loc_title + "|" + ftoa(floor(weatherValue * 100) * 0.1) + "|" + itoa(i) + "|" + timeStamp);
else
g_Campaign.AddNotification("gui/layouts/tkom_item_notification_weather.layout", "#tkom_weather_title", "#tkom_weather_desc_loc|#tkom_weather_desc_haz|#tkom_weather_desc_time|#tkom_weather_desc_timestamp", loc_title + "|" + ftoa(floor(weatherValue * 100) * 0.1) + "|#tkom_weather_timenow" + "|" + timeStamp);
return;
}
}
}
//----------------------------------------------------------
Planet RoverMars_Campaign::FindPlanet(string name)
{
for(int n = 0; n < planetsCount; n++)
{
Planet planet = planets[n];
if(planet.name == name)
return planet;
}
return NULL;
}
//----------------------------------------------------------
Planet RoverMars_Campaign::CreatePlanet(string name)
{
Planet planet = new Planet();
planet.title = "";
planet.description = "";
planet.index = planetsCount;
planets[planetsCount++] = planet;
bool loaded = planet.Load(FILEPATH_INT_WORLDS + name + ".pla");
if (!loaded)
loaded = planet.Load(FILEPATH_EXT_WORLDS + name + ".pla");
if (!loaded)
{
// Now go through addons
string addons[ADDONSMAX];
int addonsCount = GetAddons(addons);
for(int addN = 0; addN < addonsCount; addN++)
{
string addonName = addons[addN];
// Only search the addon if it is enabled via the Addons menu
if(g_Game.IsAddonActive(addonName) == false)
continue;
loaded = planet.Load("$" + addonName + ":" + FILEPATH_ADDONS_WORLDS + name + ".pla");
if (loaded)
break;
}
}
if (!loaded)
Print(String("VALIDATE PLANETS: Could not locate file for planet '" + name + "', ignoring..."));
return planet;
}
//----------------------------------------------------------
Location RoverMars_Campaign::FindLocationByPath(string path)
{
for(int n = 0; n < locationsCount; n++)
{
Location location = locations[n];
if(location.loc_path == path)
return location;
}
return NULL;
}
//----------------------------------------------------------
Location RoverMars_Campaign::FindLocation(string name)
{
for(int n = 0; n < locationsCount; n++)
{
Location location = locations[n];
if(location.name == name)
return location;
}
return NULL;
}
//----------------------------------------------------------
Location RoverMars_Campaign::FindLocationNoCase(string name)
{
strlower(name);
for(int n = 0; n < locationsCount; n++)
{
Location location = locations[n];
string locName = location.name;
strlower(locName);
if(locName == name)
return location;
}
return NULL;
}
//----------------------------------------------------------
Location RoverMars_Campaign::CreateLocation(string name)
{
Location location = new Location();
location.name = name;
if (campaignIndex == CAMPAIGN_SPACE_PROGRAM || campaignIndex == CAMPAIGN_SCENARIOS)
location.WeatherGenerateForecast(MAX_WEATHERFORECAST_HOURS, true, false, -1);
else
location.WeatherGenerateForecast(MAX_WEATHERFORECAST_HOURS, true, true, -1);
locations[locationsCount] = location;
locationsCount++;
return location;
}
//----------------------------------------------------------
void RoverMars_Campaign::DestroyLocations()
{
for(int n = locationsCount - 1; n >= 0; n--)
{
Location location = locations[n];
if(location)
{
delete location;
location = NULL;
}
locations[n] = NULL;
}
locationsCount = 0;
}
//----------------------------------------------------------
void RoverMars_Campaign::SetCurrentLocation(Location location)
{
currentLocation = location;
}
//----------------------------------------------------------
void RoverMars_Campaign::SetSelectedLocation(Location location)
{
selectedLocation = location;
}
//----------------------------------------------------------
void RoverMars_Campaign::SetUnderCursorLocation(Location location)
{
underCursorLocation = location;
}
//----------------------------------------------------------
Location RoverMars_Campaign::GetCurrentLocation()
{
return currentLocation;
}
//----------------------------------------------------------
void RoverMars_Campaign::PrintData()
{
string str;
for(local int n = 0; n < locationsCount; n++)
{
Print("");
Print("");
Location location = locations[n];
location.PrintData();
for(local int k = 0; k < location.scienceTargetsCount; k++)
{
ScienceTarget target = location.scienceTargets[k];
target.PrintData();
}
Print("");
Print("");
}
}
//----------------------------------------------------------
void RoverMars_Campaign::CreateMissingLocations()
{
string locationDefFile;
int fileAttribute;
bool validEnt;
randomize(-1); // Randomize seed
bool doSTRefresh = false;
if (campaignSTVersion != CAMPAIGN_SCIENCETARGETS_VERSION) {
Print(String("CREATE MISSING LOCATIONS: Campaign Science Targets Version changed from " + itoa(campaignSTVersion) + " to " + itoa(CAMPAIGN_SCIENCETARGETS_VERSION) + ", synchronizing science targets..."));
campaignSTVersion = CAMPAIGN_SCIENCETARGETS_VERSION;
doSTRefresh = true;
}
FindFileHandle ff = FindFile(FILEPATH_INT_WORLDS + "*.loc", locationDefFile, fileAttribute, 0);
if(ff)
{
while(true)
{
string locName = substr(locationDefFile, 0, strlen(locationDefFile) - 4);
validEnt = FileExist(FILEPATH_INT_WORLDS + locName + ".ent");
if (validEnt)
{
Location loc = FindLocation(locName);
if(!loc || doSTRefresh)
{
if(!loc)
loc = CreateLocation(locName);
if (doSTRefresh && loc.WeatherIsNull()) {
loc.loc_weatherVal = 0;
loc.WeatherGenerateForecast(MAX_WEATHERFORECAST_HOURS, false, false, -1);
}
if( !loc.Load(FILEPATH_INT_WORLDS + locationDefFile, doSTRefresh) )
Print(String("LOADLOCATIONS: Could not load .loc file for location '" + locName + "', ignoring..."));
else {
loc.loc_path = FILEPATH_INT_WORLDS + locName + ".ent";
if (g_Game && g_Game.gameMode != GAMEMODE_SCENARIO_EDITOR) {
loc.loc_loadScnObjPath = FILEPATH_INT_SCENARIOSCAMPAIGN + locName + ".scn";
bool loadedSTs = loc.GetScienceTargetsFromSCN(loc.loc_loadScnObjPath, doSTRefresh);
if (!loadedSTs)
Print(String("LOADLOCATIONS: Could not load campaign .scn file for location '" + locName + "'"));
}
}
}
}
else
Print(String("LOADLOCATIONS: Could not locate .ent file for location '" + locName + "', ignoring..."));
if(!FindNextFile(ff, locationDefFile, fileAttribute))
break;
}
CloseFindFile(ff);
}
ff = FindFile(FILEPATH_EXT_WORLDS + "*.loc", locationDefFile, fileAttribute, 0);
if(ff)
{
while(true)
{
locName = substr(locationDefFile, 0, strlen(locationDefFile) - 4);
validEnt = FileExist(FILEPATH_EXT_WORLDS + locName + ".ent");
if (validEnt)
{
loc = FindLocation(locName);
if(!loc || doSTRefresh)
{
if(!loc)
loc = CreateLocation(locName);
if (doSTRefresh && loc.WeatherIsNull()) {
loc.loc_weatherVal = 0;
loc.WeatherGenerateForecast(MAX_WEATHERFORECAST_HOURS, false, false, -1);
}
if( !loc.Load(FILEPATH_EXT_WORLDS + locationDefFile, doSTRefresh) )
Print(String("LOADLOCATIONS: Could not load custom .loc file for location '" + locName + "', ignoring..."));
else {
loc.loc_path = FILEPATH_EXT_WORLDS + locName + ".ent";
if (g_Game && g_Game.gameMode != GAMEMODE_SCENARIO_EDITOR) {
loc.loc_loadScnObjPath = FILEPATH_EXT_SCENARIOSCAMPAIGN + locName + ".scn";
loadedSTs = loc.GetScienceTargetsFromSCN(loc.loc_loadScnObjPath, doSTRefresh);
if (!loadedSTs)
Print(String("LOADLOCATIONS: Could not load custom campaign .scn file for location '" + locName + "'"));
}
}
}
}
else
Print(String("LOADLOCATIONS: Could not locate custom .ent file for location '" + locName + "', ignoring..."));
if(!FindNextFile(ff, locationDefFile, fileAttribute))
break;
}
CloseFindFile(ff);
}
// Now go through addons
string addons[ADDONSMAX];
int addonsCount = GetAddons(addons);
for(int addN = 0; addN < addonsCount; addN++)
{
string addonName = addons[addN];
// Only search the addon if it is enabled via the Addons menu
if(g_Game.IsAddonActive(addonName) == false)
continue;
ff = FindFile("$" + addonName + ":" + FILEPATH_ADDONS_WORLDS + "*.loc", locationDefFile, fileAttribute, 0);
if(ff)
{
while(true)
{
locName = substr(locationDefFile, 0, strlen(locationDefFile) - 4);
validEnt = FileExist("$" + addonName + ":" + FILEPATH_ADDONS_WORLDS + locName + ".ent");
if (validEnt)
{
loc = FindLocation(locName);
if(!loc || doSTRefresh)
{
if(!loc)
loc = CreateLocation(locName);
if (doSTRefresh && loc.WeatherIsNull()) {
loc.loc_weatherVal = 0;
loc.WeatherGenerateForecast(MAX_WEATHERFORECAST_HOURS, false, false, -1);
}
if( !loc.Load("$" + addonName + ":" + FILEPATH_ADDONS_WORLDS + locationDefFile, doSTRefresh) )
Print(String("LOADLOCATIONS: Could not load addon .loc file for location '" + locName + "', ignoring..."));
else {
loc.loc_path = "$" + addonName + ":" + FILEPATH_ADDONS_WORLDS + locName + ".ent";
if (g_Game && g_Game.gameMode != GAMEMODE_SCENARIO_EDITOR) {
loc.loc_loadScnObjPath = "$" + addonName + ":" + FILEPATH_ADDONS_SCENARIOSCAMPAIGN + locName + ".scn";
loadedSTs = loc.GetScienceTargetsFromSCN(loc.loc_loadScnObjPath, doSTRefresh);
if (!loadedSTs)
Print(String("LOADLOCATIONS: Could not load addon campaign .scn file for location '" + locName + "'"));
}
}
}
}
else
Print(String("LOADLOCATIONS: Could not locate addon .ent file for location '" + locName + "', ignoring..."));
if(!FindNextFile(ff, locationDefFile, fileAttribute))
break;
}
CloseFindFile(ff);
}
}
// Print all locations and their science targets with zones
// PrintData();
}
//----------------------------------------------------------
void RoverMars_Campaign::CreatePlanets()
{
DestroyPlanets();
for(int n = 0; n < locationsCount; n++)
{
Location location = locations[n];
if(location.loc_body == "")
continue;
Planet planet = FindPlanet(location.loc_body);
if( !planet )
planet = CreatePlanet(location.loc_body);
planet.RegisterLocation(location);
}
}
//----------------------------------------------------------
void RoverMars_Campaign::DestroyPlanets()
{
for(int n = 0; n < planetsCount; n++)
{
Planet pl = planets[n];
if (pl)
delete pl;
planets[n] = NULL;
}
planetsCount = 0;
}
/*
//----------------------------------------------------------
void RoverMars_Campaign::Monitor2Remap(StaticModel ent, bool scrnSaver, string img, int monNum)
{
if (ent)
{
string objStr = "";
for (int i = 1; i < 4; i++)
{
objStr += "$remap 'obj/structures/addons/controlpanel_scr" + itoa(i) + "' 'obj/structures/addons/controlpanel_scr" + itoa(i);
if (i == monNum)
{
if (!scrnSaver)
objStr += "_" + img + "';";
else
objStr += "_saver';";
}
else
objStr += "_saver';";
}
ent.SetObject(ent.GetVObject(), objStr);
UpdateEntity(ent);
}
}
*/
//----------------------------------------------------------
void RoverMars_Campaign::GetLastThreeLogoutVehicles(VehicleObject result[])
{
result[0] = NULL;
result[1] = NULL;
result[2] = NULL;
VehicleObject veh;
int n, v, k;
VehicleObject vehicles[256];
int vehiclesCount = 0;
for(n = 0; n < locationsCount; n++)
{
Location location = locations[n];
for(v = 0; v < location.vehiclesCount; v++)
{
veh = location.vehicles[v];
if( !veh.logoutPhoto )
continue; //last logout information not available
if( !FileExist( veh.logoutPhoto.filePath) )
continue;
vehicles[vehiclesCount++] = veh;
}
}
if(vehiclesCount < 1)
return;
for(n = 0; n < 3; n++)
{
int bestIndex = -1;
VehicleObject bestVehicle = NULL;
for(v = 0; v < vehiclesCount; v++)
{
veh = vehicles[v];
if(veh == NULL)
continue; //skip excluded items
if( bestVehicle == NULL || veh.logoutPhoto.IsGreatherThan( bestVehicle.logoutPhoto ) )
{
bestVehicle = veh;
bestIndex = v;
}
}
if(bestIndex != -1)
{
result[n] = bestVehicle;
vehicles[bestIndex] = NULL; //exclude greatest item
}
}
}
//----------------------------------------------------------
void RoverMars_Campaign::UpdateTableMonitors(bool first, bool second, bool third, bool fourth, int state)
{
VehicleObject lastThreeVehicles[3];
GetLastThreeLogoutVehicles(lastThreeVehicles);
VehicleObject monitorVehicle = NULL;
StaticModelDisplayTexture monitorsEntity = (StaticModelDisplayTexture)FindNamedEntity(g_Game.CurrentWorld, "monitors_main");
if(!monitorsEntity)
return;
string remapStr = "";
remapStr += "$remap 'obj/structures/addons/controlpanel_scr1' 'obj/structures/addons/controlpanel_scr1";
if(first)
{
monitorVehicle = lastThreeVehicles[0];
if(state && monitorVehicle)
remapStr += "_highlight";
else
remapStr += "_normal";
if(monitorVehicle)
monitorsEntity.SetTexture(0, monitorVehicle.logoutPhoto.filePath);
else
monitorsEntity.SetTexture(0, "gui/textures/blanker");
}
else
remapStr += "_normal";
remapStr += "';";
remapStr += "$remap 'obj/structures/addons/controlpanel_scr2' 'obj/structures/addons/controlpanel_scr2";
if(second)
{
monitorVehicle = lastThreeVehicles[1];
if(state && monitorVehicle)
remapStr += "_highlight";
else
remapStr += "_normal";
if(monitorVehicle)
monitorsEntity.SetTexture(1, monitorVehicle.logoutPhoto.filePath);
else
monitorsEntity.SetTexture(1, "gui/textures/blanker");
}
else
remapStr += "_normal";
remapStr += "';";
remapStr += "$remap 'obj/structures/addons/controlpanel_scr3' 'obj/structures/addons/controlpanel_scr3";
if(third)
{
monitorVehicle = lastThreeVehicles[2];
if(state && monitorVehicle)
remapStr += "_highlight";
else
remapStr += "_normal";
if(monitorVehicle)
monitorsEntity.SetTexture(2, monitorVehicle.logoutPhoto.filePath);
else
monitorsEntity.SetTexture(2, "gui/textures/blanker");
}
else
remapStr += "_normal";
remapStr += "'";
if(fourth)
{
int gg = 0; //dodelat
}
monitorsEntity.SetObject(monitorsEntity.GetVObject(), remapStr);
UpdateEntity(monitorsEntity);
}
//----------------------------------------------------------
string Photo::GetTitle()
{
string desc = location.loc_title;
if(mission)
desc += " (" + mission.mission_title + ")";
desc += " " + GetDateString();
return desc;
}
//----------------------------------------------------------
string Photo::GetDescription()
{
return GetTitle();
}
//----------------------------------------------------------
void Planet::Planet()
{
highlightRemap = "";
}
//----------------------------------------------------------
void Planet::RegisterLocation(Location loc)
{
locations[locationsCount++] = loc;
}
//----------------------------------------------------------
bool Planet::Load(string fileName)
{
const int maxTokens = 64;
string tokens[maxTokens];
tparse file = BeginParse(fileName);
if(!file)
return false;
// Location file exists, so parse through it
int line = 0;
int numTokens = ParseLine(file, line, tokens);
while(numTokens > 0)
{
string firstToken = tokens[0];
switch(firstToken)
{
case "$Planet":
{
name = tokens[1];
break;
}
case "Title":
{
title = tokens[1];
break;
}
case "Description":
{
description = tokens[1];
break;
}
case "Model":
{
model = tokens[1];
break;
}
case "HighlightRemap":
{
highlightRemap = tokens[1];
break;
}
case "CameraDist":
{
cameraDist = atof(tokens[1]);
break;
}
}
for (int i = 0; i < maxTokens; i++)
{
tokens[i] = "";
}
numTokens = ParseLine(file, ++line, tokens);
}
EndParse(file);
return true;
}
//----------------------------------------------------------
void NetPlayerTKOM::NetPlayerTKOM()
{
}
//----------------------------------------------------------
void NetPlayerTKOM::~NetPlayerTKOM()
{
if(currentVehicle)
currentVehicle.SetNetPlayer(NULL);
}
//----------------------------------------------------------
void NetPlayerTKOM::SetVehicle(Vehicle_Handler vehicle)
{
currentVehicle = vehicle;
}
//----------------------------------------------------------
bool NetPlayerTKOM::IsCallToLocal(bool isRemoteCall)
{
if(isRemoteCall)
return true;
if( g_Game.IsServer() )
return true;
return false;
}
//----------------------------------------------------------
bool NetPlayerTKOM::IsCallToServer(bool isRemoteCall)
{
if( !isRemoteCall && g_Game.IsClient() )
return true;
if( isRemoteCall && g_Game.IsServer() )
return true;
return false;
}
//----------------------------------------------------------
bool NetPlayerTKOM::IsCallToClients(bool isRemoteCall)
{
if(isRemoteCall)
return false;
if(!g_Game.IsServer())
return false;
return true;
}
//----------------------------------------------------------
void NetPlayerTKOM::RP_SelectVehicle(int vehicle, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
bool ok = SelectVehicleOnLocal(vehicle);
if(!ok && isCallToServer)
{
Print("SelectVehicleOnLocal failed")
return; //cannot select vehicle on server. do not forward this RPC to clients!!!
}
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_SELECT_VEHICLE);
adapter.WriteInt(vehicle);
}
}
}
//----------------------------------------------------------
bool NetPlayerTKOM::SelectVehicleOnLocal(int vehicle)
{
Vehicle_Handler veh = NULL;
if(vehicle > 0)
{
veh = g_Campaign.FindVehicleyByUniqueID(vehicle);
if(veh == NULL)
{
Print(String("Player " + GetName() + " try select not existing vehicle (" + itoa(vehicle) + ")"));
return false;
}
}
int oldVehicleID = 0;
//!unlink old vehicle first
if(currentVehicle)
{
oldVehicleID = currentVehicle.GetID();
currentVehicle.SetNetPlayer(NULL);
}
SetVehicle(NULL);
if(veh)
{
//link this player and vehicle
SetVehicle(veh);
veh.SetNetPlayer(this);
Print(String("Player " + GetName() + " has selected vehicle (" + itoa(vehicle) + ")"))
}
else
{
if(oldVehicleID > 0)
Print(String("Player " + GetName() + " has unselected vehicle (" + itoa(oldVehicleID) + ")"))
else
Print(String("Player " + GetName() + " has unselected vehicle"))
}
if( IsLocalPlayer() )
g_Campaign.SelectCurrentVehicle(veh);
return true;
}
//----------------------------------------------------------
void NetPlayerTKOM::RP_AddChatMessage(string message, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
g_Campaign.chatConsole.AddChatMessage( this, message );
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_ADD_CHAT_MESSAGE);
adapter.WriteString(message);
}
}
}
//----------------------------------------------------------
void NetPlayerTKOM::RP_SendPopup(bool noAlphaChange, bool clearPrevious, float time, string layout, string titStr, string descStr, string descStr2, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
if (clearPrevious)
{
g_Campaign.popupMessage.ForceClear(noAlphaChange);
g_Campaign.ClearPopupMessageQueue();
}
g_Campaign.AddPopupMessage(time, layout, titStr, descStr, descStr2);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_SEND_POPUP);
adapter.WriteBool(noAlphaChange);
adapter.WriteBool(clearPrevious);
adapter.WriteFloat(time);
adapter.WriteString(layout);
adapter.WriteString(titStr);
adapter.WriteString(descStr);
adapter.WriteString(descStr2);
}
}
}
//----------------------------------------------------------
void NetPlayerTKOM::RP_DoPopupForPlayer(int playerIndex, bool noAlphaChange, bool clearPrevious, float time, string layout, string titStr, string descStr, string descStr2, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
NetPlayer tgtPlayer = g_Game.GetNetPlayer(playerIndex);
if (tgtPlayer && tgtPlayer.IsLocalPlayer())
{
if (clearPrevious)
{
g_Campaign.popupMessage.ForceClear(noAlphaChange);
g_Campaign.ClearPopupMessageQueue();
}
g_Campaign.AddPopupMessage(time, layout, titStr, descStr, descStr2);
}
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_SEND_PLAYERPOPUP);
adapter.WriteInt(playerIndex);
adapter.WriteBool(noAlphaChange);
adapter.WriteBool(clearPrevious);
adapter.WriteFloat(time);
adapter.WriteString(layout);
adapter.WriteString(titStr);
adapter.WriteString(descStr);
adapter.WriteString(descStr2);
}
}
}
void NetPlayerTKOM::RP_DeleteInventoryItem(int itemID, int wldItemID, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
if (isCallToServer && wldItemID > 0)
{
Object_InventoryItem worldEnt = (Object_InventoryItem)FindEntityByID(g_Game.CurrentWorld, wldItemID);
if (worldEnt)
delete worldEnt;
else
Print(String("RP_DELETEINVENTORYITEM: Could not find world item by id: " + itoa(wldItemID) + "!!!"));
}
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_DELETEINVENTORYITEM: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
delete item;
UniversalClassEvent("Item_Delete", item);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_DELETE_ITEM);
adapter.WriteInt(itemID);
adapter.WriteInt(wldItemID);
}
}
}
void NetPlayerTKOM::RP_UpdateInventoryItem_GenInt(int itemID, int genInt, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_UPDATEINVENTORYITEM_GENINT: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
item.GenInt = genInt;
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_ITEM_UPDATE_GENINT);
adapter.WriteInt(itemID);
adapter.WriteInt(genInt);
}
}
}
void NetPlayerTKOM::RP_UpdateInventoryItem_GenFloat(int itemID, float genFloat, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_UPDATEINVENTORYITEM_GENFLOAT: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
item.GenFloat = genFloat;
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_ITEM_UPDATE_GENFLOAT);
adapter.WriteInt(itemID);
adapter.WriteFloat(genFloat);
}
}
}
void NetPlayerTKOM::RP_UpdateInventoryItem_GenVec(int itemID, vector genVec, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_UPDATEINVENTORYITEM_GENVEC: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
item.GenVec = genVec;
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_ITEM_UPDATE_GENVEC);
adapter.WriteInt(itemID);
adapter.WriteVector(genVec);
}
}
}
void NetPlayerTKOM::RP_UpdateInventoryItem_GenString(int itemID, string genString, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_UPDATEINVENTORYITEM_GENSTRING: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
item.SetGenString(genString);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_ITEM_UPDATE_GENSTRING);
adapter.WriteInt(itemID);
adapter.WriteString(genString);
}
}
}
void NetPlayerTKOM::RP_InventoryItemOption(int itemID, int callerID, int option, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_INVENTORYITEMOPTION: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
CharacterObject character = (CharacterObject)g_Campaign.currentLocation.FindVehicleByStoreID(callerID);
if (!character)
{
Print(String("RP_INVENTORYITEMOPTION: Could not find character by id: " + itoa(callerID) + "!!!"));
return;
}
if (!item.controller)
{
Print(String("RP_INVENTORYITEMOPTION: Inventory item (id: " + itoa(callerID) + ") does not have a controller!!!"));
return;
}
item.controller.IIController_OnInventoryOption(option, character);
UniversalClassEvent("Item_InventoryOption " + itoa(option), item);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_ITEM_OPTION);
adapter.WriteInt(itemID);
adapter.WriteInt(callerID);
adapter.WriteIntAsByte(option);
}
}
}
void NetPlayerTKOM::RP_InventoryItemEvent(int itemID, int callerID, string eventName, bool isRemoteCall)
{
bool isCallToServer = IsCallToServer(isRemoteCall);
bool isCallToClients = IsCallToClients(isRemoteCall);
if( IsCallToLocal(isRemoteCall) )
{
// Call on local
InventoryItemObject item = Global_GetInventoryItemByID(itemID);
if (!item)
{
Print(String("RP_INVENTORYITEMEVENT: Could not find inventory item by id: " + itoa(itemID) + "!!!"));
return;
}
CharacterObject character = NULL;
if (callerID > 0)
character = (CharacterObject)g_Campaign.currentLocation.FindVehicleByStoreID(callerID);
if (!character && callerID > 0)
{
Print(String("RP_INVENTORYITEMEVENT: Could not find character by id: " + itoa(callerID) + "!!!"));
return;
}
if (!item.controller)
{
Print(String("RP_INVENTORYITEMEVENT: Inventory item (id: " + itoa(callerID) + ") does not have a controller!!!"));
return;
}
item.controller.IIController_OnInventoryEvent(eventName, character);
UniversalClassEvent("Item_InventoryEvent " + eventName, item);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_ITEM_EVENT);
adapter.WriteInt(itemID);
adapter.WriteInt(callerID);
adapter.WriteString(eventName);
}
}
}
void NetPlayerTKOM::RP_MoveToOtherInventory(int id, int invIndex, int invItemIndex, int newID, int newInvIndex, int newSlot, bool ignoreSlotTypes, bool isRemoteCall)
{
// Cannot perform action on server, so cancel
if (g_Game.IsServer() && !CanMoveToOtherInventory(id, invIndex, invItemIndex, newID, newInvIndex, newSlot))
return;
if( IsCallToLocal(isRemoteCall) )
MoveToOtherInventory(id, invIndex, invItemIndex, newID, newInvIndex, newSlot, ignoreSlotTypes); //do on local
if( IsCallToServer(isRemoteCall) || IsCallToClients(isRemoteCall) )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_MOVE_TO_OTHER);
adapter.WriteInt(id);
adapter.WriteInt(invIndex);
adapter.WriteInt(invItemIndex);
adapter.WriteInt(newID);
adapter.WriteInt(newInvIndex);
adapter.WriteInt(newSlot);
adapter.WriteBool(ignoreSlotTypes);
}
}
}
void NetPlayerTKOM::RP_MoveWithinInventory(int id, int invIndex, int invItemIndex, int newSlot, bool ignoreSlotTypes, bool isRemoteCall)
{
// Cannot perform action on server, so cancel
if (g_Game.IsServer() && !CanMoveWithinInventory(id, invIndex, invItemIndex, newSlot))
return;
if( IsCallToLocal(isRemoteCall) )
MoveWithinInventory(id, invIndex, invItemIndex, newSlot, ignoreSlotTypes); //do on local
if( IsCallToServer(isRemoteCall) || IsCallToClients(isRemoteCall) )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_MOVE_WITHIN);
adapter.WriteInt(id);
adapter.WriteInt(invIndex);
adapter.WriteInt(invItemIndex);
adapter.WriteInt(newSlot);
adapter.WriteBool(ignoreSlotTypes);
}
}
}
void NetPlayerTKOM::RP_MoveToWorld(int id, int invIndex, int invItemIndex, int itmWorldID, int grabUnitID, vector invItemMat[4], bool isRemoteCall)
{
// Cannot perform action on server, so cancel
if (g_Game.IsServer() && !CanMoveToWorld(id, invIndex, invItemIndex))
return;
if( IsCallToLocal(isRemoteCall) )
itmWorldID = MoveToWorld(id, invIndex, invItemIndex, itmWorldID, grabUnitID, invItemMat); //do on local
if( IsCallToServer(isRemoteCall) || IsCallToClients(isRemoteCall) )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_TO_WORLD);
adapter.WriteInt(id);
adapter.WriteInt(invIndex);
adapter.WriteInt(invItemIndex);
adapter.WriteInt(itmWorldID);
adapter.WriteInt(grabUnitID);
adapter.WriteMatrixAsQuaternionVector(invItemMat);
}
}
}
void NetPlayerTKOM::RP_MoveToInventory(int id, int invIndex, int slot, int itmID, bool ignoreSlotTypes, bool isRemoteCall)
{
// Cannot perform action on server, so cancel
if (g_Game.IsServer() && !CanMoveToInventory(id, invIndex, slot, itmID))
return;
if( IsCallToLocal(isRemoteCall) )
itmID = MoveToInventory(id, invIndex, slot, itmID, ignoreSlotTypes); //do on local
if( IsCallToServer(isRemoteCall) || IsCallToClients(isRemoteCall) )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = RPCall(RPC_INVENTORY_MOVE_TO);
adapter.WriteInt(id);
adapter.WriteInt(invIndex);
adapter.WriteInt(slot);
adapter.WriteInt(itmID);
adapter.WriteBool(ignoreSlotTypes);
}
}
}
bool NetPlayerTKOM::CanMoveToOtherInventory(int id, int invIndex, int invItemIndex, int newID, int newInvIndex, int newSlot)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
return false;
Inventory newInventory = GetInventoryByIDAndIndex(newID, newInvIndex);
if (!newInventory)
return false;
InventoryItemObject invItem = inventory.slotItem[invItemIndex];
if (!invItem)
return false;
invItem = newInventory.slotItem[newSlot];
if (invItem)
return false;
return true;
}
bool NetPlayerTKOM::CanMoveWithinInventory(int id, int invIndex, int invItemIndex, int newSlot)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
return false;
InventoryItemObject invItem = inventory.slotItem[invItemIndex];
if (!invItem)
return false;
invItem = inventory.slotItem[newSlot];
if (invItem)
return false;
return true;
}
bool NetPlayerTKOM::CanMoveToWorld(int id, int invIndex, int invItemIndex)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
return false;
InventoryItemObject invItem = inventory.slotItem[invItemIndex];
if (!invItem)
return false;
return true;
}
bool NetPlayerTKOM::CanMoveToInventory(int id, int invIndex, int slot, int itmID)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
return false;
Object_InventoryItem invItemEnt = (Object_InventoryItem)FindEntityByID(g_Game.CurrentWorld, itmID);
if (!invItemEnt)
return false;
InventoryItemObject invItem = inventory.slotItem[slot];
if (invItem)
return false;
return true;
}
//----------------------------------------------------------
#ifdef STEAMWORKS
string NetPlayerTKOM::GetUniqueSteamUserID()
{
string uniqueSteamID = GetSteamUserID();
int idMatches = 0;
for(int n = 0; n < g_Game.GetNetPlayersCount(); n++)
{
NetPlayerTKOM pla = (NetPlayerTKOM)g_Game.GetNetPlayer(n);
if (pla == this)
break;
if (uniqueSteamID == pla.GetSteamUserID())
idMatches++;
}
if (idMatches > 0)
uniqueSteamID += "_" + itoa(idMatches);
return uniqueSteamID;
}
#endif
//----------------------------------------------------------
bool NetPlayerTKOM::IsTyping()
{
return typing;
}
//----------------------------------------------------------
void NetPlayerTKOM::OnUpdate(float timeslice) //every frame
{
if( IsLocalPlayer() && g_Campaign && g_Campaign.chatConsole )
typing = g_Campaign.chatConsole.HasEditBoxFocus();
// if(!isInitialized)
// return;
}
//----------------------------------------------------------
void NetPlayerTKOM::OnNetObjectInitSend( PacketOutputAdapter output )
{
if( IsServerPlayer() )
g_Campaign.OnNetObjectInitSend(output); //as first
}
//----------------------------------------------------------
void NetPlayerTKOM::OnNetObjectInitReceived( PacketInputAdapter input )
{
if( IsServerPlayer() )
g_Campaign.OnNetObjectInitReceived(input); //as first
}
//----------------------------------------------------------
void NetPlayerTKOM::OnNetObjectAfterInitSend( PacketOutputAdapter output )
{
if( IsServerPlayer() )
g_Campaign.OnNetObjectAfterInitSend(output); //as first
int vehicleToSelect = 0;
if(currentVehicle)
vehicleToSelect = currentVehicle.GetID();
output.WriteInt(vehicleToSelect);
isInitialized = true;
}
//----------------------------------------------------------
void NetPlayerTKOM::OnNetObjectAfterInitReceived( PacketInputAdapter input )
{
if( IsServerPlayer() )
g_Campaign.OnNetObjectAfterInitReceived(input); //as first
int vehicleToSelect = input.ReadInt();
if(vehicleToSelect > 0)
SelectVehicleOnLocal(vehicleToSelect); //selection of eventual vehicle must be executed here, in safe time while all netobjects are created
isInitialized = true; //now is player completly initialized, this is signal to possible join to game
}
int DF_LOCAL_GENRATED = 1;
//----------------------------------------------------------
void NetPlayerTKOM::OnNetUpdate( PacketOutputAdapter output )
{
if( IsServerPlayer() )
g_Campaign.OnNetUpdate(output); //as first
int dataFlags = 0;
if( IsLocalPlayer() || g_Game.IsServer() )
dataFlags = dataFlags | DF_LOCAL_GENRATED;
output.WriteInt(dataFlags);
if(dataFlags & DF_LOCAL_GENRATED)
output.WriteBool(typing);
}
//----------------------------------------------------------
bool NetPlayerTKOM::OnNetMessage( PacketInputAdapter input )
{
if( IsServerPlayer() )
g_Campaign.OnNetMessage(input); //as first
int dataFlags = input.ReadInt();
if(dataFlags & DF_LOCAL_GENRATED)
{
if( IsLocalPlayer() )
input.ReadBool(); //dummy read
else
typing = input.ReadBool();
}
return true;
}
//----------------------------------------------------------
bool NetPlayerTKOM::OnRPC(int proc, PacketInputAdapter input)
{
switch(proc)
{
case RPC_SELECT_VEHICLE:
{
RP_SelectVehicle( input.ReadInt(), true );
break;
}
case RPC_ADD_CHAT_MESSAGE:
{
RP_AddChatMessage(input.ReadString(), true );
break;
}
case RPC_SEND_POPUP:
{
RP_SendPopup(input.ReadBool(), input.ReadBool(), input.ReadFloat(), input.ReadString(), input.ReadString(), input.ReadString(), input.ReadString(), true);
break;
}
case RPC_SEND_PLAYERPOPUP:
{
RP_DoPopupForPlayer(input.ReadInt(), input.ReadBool(), input.ReadBool(), input.ReadFloat(), input.ReadString(), input.ReadString(), input.ReadString(), input.ReadString(), true);
break;
}
case RPC_INVENTORY_DELETE_ITEM:
{
RP_DeleteInventoryItem(input.ReadInt(), input.ReadInt(), true );
break;
}
case RPC_INVENTORY_ITEM_UPDATE_GENINT:
{
RP_UpdateInventoryItem_GenInt(input.ReadInt(), input.ReadInt(), true );
break;
}
case RPC_INVENTORY_ITEM_UPDATE_GENFLOAT:
{
RP_UpdateInventoryItem_GenFloat(input.ReadInt(), input.ReadFloat(), true );
break;
}
case RPC_INVENTORY_ITEM_UPDATE_GENVEC:
{
RP_UpdateInventoryItem_GenVec(input.ReadInt(), input.ReadVector(), true );
break;
}
case RPC_INVENTORY_ITEM_UPDATE_GENSTRING:
{
RP_UpdateInventoryItem_GenString(input.ReadInt(), input.ReadString(), true );
break;
}
case RPC_INVENTORY_ITEM_OPTION:
{
RP_InventoryItemOption(input.ReadInt(), input.ReadInt(), input.ReadIntAsByte(), true );
break;
}
case RPC_INVENTORY_ITEM_EVENT:
{
RP_InventoryItemEvent(input.ReadInt(), input.ReadInt(), input.ReadString(), true );
break;
}
case RPC_INVENTORY_MOVE_TO:
{
RP_MoveToInventory(input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadBool(), true);
break;
}
case RPC_INVENTORY_MOVE_TO_OTHER:
{
RP_MoveToOtherInventory(input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadBool(), true);
break;
}
case RPC_INVENTORY_MOVE_WITHIN:
{
RP_MoveWithinInventory(input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadInt(), input.ReadBool(), true);
break;
}
case RPC_INVENTORY_TO_WORLD:
{
int id = input.ReadInt();
int invIndex = input.ReadInt();
int invItemIndex = input.ReadInt();
int itmWorldID = input.ReadInt();
int grabUnitID = input.ReadInt();
vector invItemMat[4];
input.ReadMatrixAsQuaternionVector(invItemMat);
RP_MoveToWorld(id, invIndex, invItemIndex, itmWorldID, grabUnitID, invItemMat, true);
break;
}
default:
{
g_Campaign.OnRPC(proc, input);
}
}
return true;
}
//----------------------------------------------------------
void Location::OnNetObjectInitSend( PacketOutputAdapter output )
{
local int r, x, y, numChanged;
// Send resource data
output.WriteIntAsUByte(ResourcesNum);
for (r = 0; r < ResourcesNum; r++)
{
Resource_Base rscEnt = Resources[r];
output.WriteStaticString(rscEnt.name);
output.WriteStaticString(rscEnt.title);
output.WriteStaticString(rscEnt.desc);
output.WriteVector(rscEnt.displayColor);
output.WriteIntAsUByte(rscEnt.areaType);
output.WriteInt(rscEnt.distributeSeed);
output.WriteInt(rscEnt.distrib_MaxAmountTotal);
output.WriteFloat(rscEnt.distrib_Clumping);
numChanged = 0;
for (x = 0; x < rscEnt.distrib_SectorNumX; x++)
{
for (y = 0; y < rscEnt.distrib_SectorNumY; y++)
{
if (!rscEnt.Changed[x][y])
continue;
numChanged++;
}
}
output.WriteInt(numChanged);
for (x = 0; x < rscEnt.distrib_SectorNumX; x++)
{
for (y = 0; y < rscEnt.distrib_SectorNumY; y++)
{
if (!rscEnt.Changed[x][y])
continue;
output.WriteIntAsUByte(x);
output.WriteIntAsUByte(y);
output.WriteInt(rscEnt.Amount[x][y]);
}
}
}
// Send revealed sector data
for (r = 0; r < 3; r++)
{
numChanged = 0;
for (x = 0; x < ResourcesSectorNum_X; x++)
{
for (y = 0; y < ResourcesSectorNum_Y; y++)
{
if (r == 0 && !ResourceDiscovered_Ground[x][y])
continue;
if (r == 1 && !ResourceDiscovered_Surface[x][y])
continue;
if (r == 2 && !ResourceDiscovered_Atmospheric[x][y])
continue;
numChanged++;
}
}
output.WriteInt(numChanged);
for (x = 0; x < ResourcesSectorNum_X; x++)
{
for (y = 0; y < ResourcesSectorNum_Y; y++)
{
if (r == 0 && !ResourceDiscovered_Ground[x][y])
continue;
if (r == 1 && !ResourceDiscovered_Surface[x][y])
continue;
if (r == 2 && !ResourceDiscovered_Atmospheric[x][y])
continue;
output.WriteIntAsUByte(x);
output.WriteIntAsUByte(y);
}
}
}
}
//----------------------------------------------------------
void Location::OnNetObjectInitReceived( PacketInputAdapter input )
{
local int n, r, x, y, numChanged;
DestroyResources();
ClearDiscoveredSectors();
// Get resource data
int numRes = input.ReadIntAsUByte();
for (r = 0; r < numRes; r++)
{
string resName = input.ReadStaticString();
string resTitle = input.ReadStaticString();
string resDesc = input.ReadStaticString();
vector resColor = input.ReadVector();
int resType = input.ReadIntAsUByte();
int resSeed = input.ReadInt();
int resAmt = input.ReadInt();
float resClump = input.ReadFloat();
Resource_Base rscEnt = AddResourceType(resName, resTitle, resDesc, resAmt, resClump, resColor, resType);
rscEnt.distributeSeed = resSeed;
rscEnt.DistributeResource();
numChanged = input.ReadInt();
for (n = 0; n < numChanged; n++)
{
x = input.ReadIntAsUByte();
y = input.ReadIntAsUByte();
int amt = input.ReadInt();
rscEnt.SetAmountInSector(amt, x, y);
}
}
// Get revealed sector data
for (r = 0; r < 3; r++)
{
numChanged = input.ReadInt();
for (n = 0; n < numChanged; n++)
{
x = input.ReadIntAsUByte();
y = input.ReadIntAsUByte();
if (r == 0)
DiscoverResourceAtSector(RESOURCE_AREATYPE_GROUND, x, y, 0, false);
if (r == 1)
DiscoverResourceAtSector(RESOURCE_AREATYPE_SURFACE, x, y, 0, false);
if (r == 2)
DiscoverResourceAtSector(RESOURCE_AREATYPE_ATMOSPHERIC, x, y, 0, false);
}
}
}
//----------------------------------------------------------
void Location::OnNetObjectAfterInitSend( PacketOutputAdapter output )
{
}
//----------------------------------------------------------
void Location::OnNetObjectAfterInitReceived( PacketInputAdapter input )
{
}
//----------------------------------------------------------
void Location::OnNetUpdate( PacketOutputAdapter output )
{
}
//----------------------------------------------------------
bool Location::OnNetMessage( PacketInputAdapter input )
{
return true;
}
//----------------------------------------------------------
bool Location::OnRPC(int proc, PacketInputAdapter input)
{
switch(proc)
{
case RPC_LOC_RESOURCECHANGED:
{
int resIndex = input.ReadIntAsUByte();
int sectorX = input.ReadIntAsUByte();
int sectorY = input.ReadIntAsUByte();
int amount = input.ReadInt();
Resource_Base resEnt = Resources[resIndex];
if (resEnt)
resEnt.SetAmountInSector(amount, sectorX, sectorY);
break;
}
}
return true;
}
//----------------------------------------------------------
void Location::RP_UpdateResource(int resIndex, int sectorX, int sectorY, int amount, bool isRemoteCall)
{
if (g_Game.IsClient())
return;
if( g_Game.CanRPCall() )
{
//if local computer is server: send message to all clients
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
PacketOutputAdapter adapter = netPlayer.RPCall(RPC_LOC_RESOURCECHANGED);
adapter.WriteIntAsUByte(resIndex);
adapter.WriteIntAsUByte(sectorX);
adapter.WriteIntAsUByte(sectorY);
adapter.WriteInt(amount);
}
}
//----------------------------------------------------------
void RagdollObject::NetSendData( PacketOutputAdapter output )
{
int n;
output.WriteString( cfgFile );
output.WriteBool( NoStore );
output.WriteBool( isNetwork );
output.WriteInt( interactionLayer );
output.WriteString( scriptPath );
output.WriteInt( joints_num );
for(n = 0; n < joints_num; n++)
{
output.WriteVector( joints_angles[n] );
output.WriteVector( joints_limits_lo[n] );
output.WriteVector( joints_limits_hi[n] );
output.WriteFloat( joints_spring_stiff[n] );
output.WriteFloat( joints_spring_damp[n] );
output.WriteInt( joints_part1[n] );
output.WriteInt( joints_part2[n] );
}
output.WriteInt(blocks_num);
for(n = 0; n < blocks_num; n++)
{
output.WriteInt( blocks_part1[n] );
output.WriteInt( blocks_part2[n] );
}
output.WriteInt(parts_num);
for(n = 0; n < parts_num; n++)
{
output.WriteFloat( parts_mass[n] );
output.WriteString( parts_models[n] );
output.WriteString( parts_name[n] );
output.WriteBool( parts_static[n] );
output.WriteBool( parts_nophys[n] );
output.WriteVector( parts_pos[n] );
output.WriteVector( parts_ang[n] );
output.WriteString( parts_conPtcSnd[n] );
output.WriteVector( parts_wmat0[n] );
output.WriteVector( parts_wmat1[n] );
output.WriteVector( parts_wmat2[n] );
output.WriteVector( parts_wmat3[n] );
output.WriteVector( parts_velLin[n] );
output.WriteVector( parts_velAng[n] );
}
for (n = 0; n < RAGDOLL_GENVARS; n++)
{
output.WriteFloat( GenFloats[n] );
output.WriteInt( GenInts[n] );
output.WriteVector( GenVecs[n] );
output.WriteString( GenStrings[n] );
}
}
//----------------------------------------------------------
void RagdollObject::NetReceiveData( PacketInputAdapter input )
{
int n;
cfgFile = input.ReadString();
NoStore = input.ReadBool();
isNetwork = input.ReadBool();
interactionLayer = input.ReadInt();
scriptPath = input.ReadString();
joints_num = input.ReadInt();
for(n = 0; n < joints_num; n++)
{
joints_angles[n] = input.ReadVector();
joints_limits_lo[n] = input.ReadVector();
joints_limits_hi[n] = input.ReadVector();
joints_spring_stiff[n] = input.ReadFloat();
joints_spring_damp[n] = input.ReadFloat();
joints_part1[n] = input.ReadInt();
joints_part2[n] = input.ReadInt();
}
blocks_num = input.ReadInt();
for(n = 0; n < blocks_num; n++)
{
blocks_part1[n] = input.ReadInt();
blocks_part2[n] = input.ReadInt();
}
parts_num = input.ReadInt();
for(n = 0; n < parts_num; n++)
{
parts_mass[n] = input.ReadFloat();
parts_models[n] = input.ReadString();
parts_name[n] = input.ReadString();
parts_static[n] = input.ReadBool();
parts_nophys[n] = input.ReadBool();
parts_pos[n] = input.ReadVector();
parts_ang[n] = input.ReadVector();
parts_conPtcSnd[n] = input.ReadString();
parts_wmat0[n] = input.ReadVector();
parts_wmat1[n] = input.ReadVector();
parts_wmat2[n] = input.ReadVector();
parts_wmat3[n] = input.ReadVector();
parts_velLin[n] = input.ReadVector();
parts_velAng[n] = input.ReadVector();
}
for (n = 0; n < RAGDOLL_GENVARS; n++)
{
GenFloats[n] = input.ReadFloat();
GenInts[n] = input.ReadInt();
GenVecs[n] = input.ReadVector();
GenStrings[n] = input.ReadString();
}
}
//----------------------------------------------------------
void VehicleObject::NetSendData( PacketOutputAdapter output )
{
int n, o;
output.WriteStaticString(defFile);
output.WriteStaticString(mapIcon);
output.WriteStaticString(guiIcon);
output.WriteStaticString(previewImage);
output.WriteInt(dockPort_num);
for(n = 0; n < dockPort_num; n++)
{
output.WriteInt( dockPort_dockedID[n] );
output.WriteInt( dockPort_portIndex[n] );
output.WriteInt( dockPort_part[n] );
output.WriteVector( dockPort_pos[n] );
output.WriteVector( dockPort_ang[n] );
output.WriteFloat( dockPort_Astress[n] );
output.WriteFloat( dockPort_Lstress[n] );
output.WriteFloat( dockPort_undockForce[n] );
output.WriteFloat( dockPort_undockTime[n] );
output.WriteStaticString( dockPort_type[n] );
}
output.WriteInt(joints_num);
for(n = 0; n < joints_num; n++)
{
output.WriteVector( joints_angles[n] );
output.WriteVector( joints_limits_lo[n] );
output.WriteVector( joints_limits_hi[n] );
output.WriteBool( joints_isLODed[n] );
output.WriteInt( joints_type[n] );
output.WriteInt( joints_part1[n] );
output.WriteInt( joints_part2[n] );
output.WriteFloat( joints_Astress[n] );
output.WriteFloat( joints_Lstress[n] );
output.WriteStaticString( joints_breakPtcSnd[n] );
output.WriteInt( joints_FXIndex[n] );
output.WriteFloat( joints_pwrdrain[n] );
output.WriteBool( joints_noDelete[n] );
}
output.WriteInt(blocks_num);
for(n = 0; n < blocks_num; n++)
{
output.WriteInt( blocks_part1[n] );
output.WriteInt( blocks_part2[n] );
output.WriteBool( blocks_noDelete[n] );
}
output.WriteInt(parts_num);
for(n = 0; n < parts_num; n++)
{
output.WriteFloat( parts_pwrdrain[n] );
output.WriteFloat( parts_damage[n] );
output.WriteInt( parts_tough[n] );
output.WriteFloat( parts_mass[n] );
output.WriteStaticString( parts_models[n] );
output.WriteStaticString( parts_types[n] );
output.WriteStaticString( parts_subtypes[n] );
output.WriteStaticString( parts_title[n] );
output.WriteStaticString( parts_detailsTitle[n] );
output.WriteStaticString( parts_detailsStatus[n] );
output.WriteVector( parts_pos[n] );
output.WriteVector( parts_ang[n] );
output.WriteVector( parts_wmat0[n] );
output.WriteVector( parts_wmat1[n] );
output.WriteVector( parts_wmat2[n] );
output.WriteVector( parts_wmat3[n] );
output.WriteVector( parts_velLin[n] );
output.WriteVector( parts_velAng[n] );
output.WriteVector( parts_genVec[n] );
output.WriteVector( parts_genVec2[n] );
output.WriteVector( parts_genVec3[n] );
output.WriteVector( parts_genVec4[n] );
output.WriteVector( parts_genVec5[n] );
output.WriteVector( parts_genVec6[n] );
output.WriteStaticString( parts_conPtcSnd[n] );
output.WriteInt( parts_storedParent[n] );
}
for(n = 0; n < MAX_VEHICLES_GENSTRINGNUM; n++)
{
output.WriteString( GenStrings[n] );
}
output.WriteInt(statcons_num);
for(n = 0; n < statcons_num; n++)
{
output.WriteInt( statcons_part1[n] );
output.WriteInt( statcons_part2[n] );
}
output.WriteInt(ctrl_num);
for(n = 0; n < ctrl_num; n++)
{
output.WriteStaticString( ctrl_types[n] );
}
output.WriteInt(script_num);
for(n = 0; n < script_num; n++)
{
output.WriteStaticString( script_Path[n] );
}
output.WriteInt(ctrlbase_num);
for(n = 0; n < ctrlbase_num; n++)
output.WriteInt( ctrlbase_parts[n] );
output.WriteBool( isMobile );
output.WriteBool( isSpace );
output.WriteBool( isGround );
output.WriteBool( isNetwork );
output.WriteString( name );
output.WriteVector( LandingZone );
output.WriteBool( genMis_AllowGenerate );
output.WriteInt( cams_mainMode );
output.WriteInt( Team );
output.WriteBool( NightCamLEDs );
output.WriteBool( NoStore );
output.WriteString( Owner_SteamID );
output.WriteString( Owner_SteamName );
output.WriteStaticString( cfgFile );
output.WriteInt(interactionLayer );
/**===========================================================**/
/**================== WRITE INVENTORIES ======================**/
/**===========================================================**/
Inventory inventory;
int inventoryNum = 0;
for(n = 0; n < INVENTORY_PEROBJECT_MAX; n++) // First count total inventories
{
inventory = inventories[n];
if (inventory)
inventoryNum++;
}
output.WriteInt(inventoryNum);
for(n = 0; n < INVENTORY_PEROBJECT_MAX; n++) // Now write each inventory
{
inventory = inventories[n];
if (!inventory)
continue;
output.WriteInt(n);
output.WriteStaticString(inventory.name);
output.WriteInt(inventories_partNum[n]);
output.WriteStaticString(inventory.layoutPath);
output.WriteStaticString(inventory.highlightText);
output.WriteStaticString(inventory.highlightImage);
output.WriteInt(inventory.slotNum);
for(o = 0; o < inventory.slotNum; o++) // Write slots for each inventory
{
output.WriteStaticString(inventory.slotType[o]);
}
int invItemNum = inventory.GetTotalItemCount();
output.WriteInt(invItemNum);
InventoryItemObject invItem;
for(o = 0; o < inventory.slotNum; o++) // Now write each item in the inventory
{
invItem = inventory.slotItem[o];
if (!invItem)
continue;
output.WriteInt(invItem.GetItemID());
output.WriteInt(o);
output.WriteStaticString(invItem.itemTitle);
output.WriteStaticString(invItem.itemDesc);
output.WriteStaticString(invItem.itemImage);
output.WriteStaticString(invItem.itemScript);
output.WriteStaticString(invItem.configFile);
output.WriteStaticString(invItem.modelPath);
output.WriteStaticString(invItem.remapPath);
output.WriteStaticString(invItem.fxPath);
output.WriteFloat(invItem.modelMass);
output.WriteInt(invItem.validSlotTypesNum);
for(int vs = 0; vs < invItem.validSlotTypesNum; vs++)
{
output.WriteStaticString(invItem.validSlotTypes[vs]);
}
output.WriteInt(invItem.GenInt);
output.WriteFloat(invItem.GenFloat);
output.WriteVector(invItem.GenVec);
output.WriteString(invItem.GenString);
}
}
}
//----------------------------------------------------------
void VehicleObject::NetReceiveData( PacketInputAdapter input )
{
int n, o;
defFile = input.ReadStaticString();
mapIcon = input.ReadStaticString();
guiIcon = input.ReadStaticString();
previewImage = input.ReadStaticString();
dockPort_num = input.ReadInt();
for(n = 0; n < dockPort_num; n++)
{
dockPort_dockedID[n] = input.ReadInt();
dockPort_portIndex[n] = input.ReadInt();
dockPort_part[n] = input.ReadInt();
dockPort_pos[n] = input.ReadVector();
dockPort_ang[n] = input.ReadVector();
dockPort_Astress[n] = input.ReadFloat();
dockPort_Lstress[n] = input.ReadFloat();
dockPort_undockForce[n] = input.ReadFloat();
dockPort_undockTime[n] = input.ReadFloat();
dockPort_type[n] = input.ReadStaticString();
}
joints_num = input.ReadInt();
for(n = 0; n < joints_num; n++)
{
joints_angles[n] = input.ReadVector();
joints_limits_lo[n] = input.ReadVector();
joints_limits_hi[n] = input.ReadVector();
joints_isLODed[n] = input.ReadBool();
joints_type[n] = input.ReadInt();
joints_part1[n] = input.ReadInt();
joints_part2[n] = input.ReadInt();
joints_Astress[n] = input.ReadFloat();
joints_Lstress[n] = input.ReadFloat();
joints_breakPtcSnd[n] = input.ReadStaticString();
joints_FXIndex[n] = input.ReadInt();
joints_pwrdrain[n] = input.ReadFloat();
joints_noDelete[n] = input.ReadBool();
}
blocks_num = input.ReadInt();
for(n = 0; n < blocks_num; n++)
{
blocks_part1[n] = input.ReadInt();
blocks_part2[n] = input.ReadInt();
blocks_noDelete[n] = input.ReadBool();
}
parts_num = input.ReadInt();
for(n = 0; n < parts_num; n++)
{
parts_pwrdrain[n] = input.ReadFloat();
parts_damage[n] = input.ReadFloat();
parts_tough[n] = input.ReadInt();
parts_mass[n] = input.ReadFloat();
parts_models[n] = input.ReadStaticString();
parts_types[n] = input.ReadStaticString();
parts_subtypes[n] = input.ReadStaticString();
parts_title[n] = input.ReadStaticString();
parts_detailsTitle[n] = input.ReadStaticString();
parts_detailsStatus[n] = input.ReadStaticString();
parts_pos[n] = input.ReadVector();
parts_ang[n] = input.ReadVector();
parts_wmat0[n] = input.ReadVector();
parts_wmat1[n] = input.ReadVector();
parts_wmat2[n] = input.ReadVector();
parts_wmat3[n] = input.ReadVector();
parts_velLin[n] = input.ReadVector();
parts_velAng[n] = input.ReadVector();
parts_genVec[n] = input.ReadVector();
parts_genVec2[n] = input.ReadVector();
parts_genVec3[n] = input.ReadVector();
parts_genVec4[n] = input.ReadVector();
parts_genVec5[n] = input.ReadVector();
parts_genVec6[n] = input.ReadVector();
parts_conPtcSnd[n] = input.ReadStaticString();
parts_storedParent[n] = input.ReadInt();
}
for(n = 0; n < MAX_VEHICLES_GENSTRINGNUM; n++)
{
GenStrings[n] = input.ReadString();
}
statcons_num = input.ReadInt();
for(n = 0; n < statcons_num; n++)
{
statcons_part1[n] = input.ReadInt();
statcons_part2[n] = input.ReadInt();
}
ctrl_num = input.ReadInt();
for(n = 0; n < ctrl_num; n++)
{
ctrl_types[n] = input.ReadStaticString();
}
script_num = input.ReadInt();
for(n = 0; n < script_num; n++)
{
script_Path[n] = input.ReadStaticString();
}
ctrlbase_num = input.ReadInt();
for(n = 0; n < ctrlbase_num; n++)
ctrlbase_parts[n] = input.ReadInt();
isMobile = input.ReadBool();
isSpace = input.ReadBool();
isGround = input.ReadBool();
isNetwork = input.ReadBool();
name = input.ReadString();
LandingZone = input.ReadVector();
genMis_AllowGenerate = input.ReadBool();
cams_mainMode = input.ReadInt();
Team = input.ReadInt();
NightCamLEDs = input.ReadBool();
NoStore = input.ReadBool();
SetOwnerSteamID(input.ReadString());
SetOwnerSteamName(input.ReadString());
StoreCFGPathName(input.ReadStaticString());
interactionLayer = input.ReadInt();
/**===========================================================**/
/**=================== READ INVENTORIES ======================**/
/**===========================================================**/
Inventory inventory;
int inventoryNum = input.ReadInt();
for(n = 0; n < inventoryNum; n++)
{
int invIndex = input.ReadInt();
string invName = input.ReadStaticString();
int invPart = input.ReadInt();
string invLayout = input.ReadStaticString();
string invHiText = input.ReadStaticString();
string invHiImg = input.ReadStaticString();
int invSlotNum = input.ReadInt();
string invSlotTypes[INVENTORY_SLOTS_MAX];
for(o = 0; o < invSlotNum; o++)
{
invSlotTypes[o] = input.ReadStaticString();
}
CreateInventory(invIndex, invName, invPart, invLayout, invHiText, invHiImg, invSlotNum, invSlotTypes);
inventory = inventories[invIndex];
if (!inventory)
CallError("VehicleObject::NetReceiveData()", "Could not create inventory on client from received data! Index: " + itoa(invIndex));
int invItemNum = input.ReadInt();
for(o = 0; o < invItemNum; o++)
{
int invItemID = input.ReadInt();
int invItemIndex = input.ReadInt();
string invItemTitle = input.ReadStaticString();
string invItemDesc = input.ReadStaticString();
string invItemImg = input.ReadStaticString();
string invItemScript = input.ReadStaticString();
string invItemCFG = input.ReadStaticString();
string invItemMdl = input.ReadStaticString();
string invItemRmp = input.ReadStaticString();
string invItemFX = input.ReadStaticString();
float invItemMass = input.ReadFloat();
string invItemValidSlots = "";
int invValidSlotsNum = input.ReadInt();
for(int vs = 0; vs < invValidSlotsNum; vs++)
{
invItemValidSlots += input.ReadStaticString();
if (vs < invValidSlotsNum - 1)
invItemValidSlots += " ";
}
int itemGenInt = input.ReadInt();
float itemGenFloat = input.ReadFloat();
vector itemGenVec = input.ReadVector();
string itemGenStr = input.ReadString();
inventory.SpawnStoredItemObject(invItemID, invItemIndex, invItemTitle, invItemDesc, invItemImg, invItemScript, invItemCFG, invItemMdl, invItemRmp, invItemFX, invItemMass, invItemValidSlots, itemGenInt, itemGenFloat, itemGenVec, itemGenStr);
}
}
}
//----------------------------------------------------------
void Inventory::SetSlotType(int index, string type)
{
if (index >= slotNum)
return;
slotType[index] = type;
}
void Inventory::ClearInventory(bool deleteSlots)
{
if (deleteSlots)
slotNum = 0;
for (int i = 0; i < INVENTORY_SLOTS_MAX; i++)
{
slotItem[i] = NULL;
slotType[i] = "";
slotHighlight[i] = false;
}
}
void Inventory::DeleteInventoryItems(bool deleteSlots)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
{
item.inventoryParent = NULL;
item.inventorySlot = -1;
delete item;
}
slotItem[i] = NULL;
}
ClearInventory(deleteSlots);
}
void Inventory::CreateInventoryItemsIDs()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
{
item.CreateID();
item.RestoreInvItemID();
}
}
}
bool Inventory::GetSlotFree(int index)
{
if (index >= slotNum)
return false;
if (slotItem[index])
return false;
return true;
}
int Inventory::GetSlotByItem(InventoryItemObject item)
{
for (int i = 0; i < slotNum; i++)
{
if (item == slotItem[i])
return i;
}
return -1;
}
int Inventory::GetFreeSlotForItem(InventoryItemObject item, bool ignoreSlotTypes, bool fromEnd)
{
local int s;
if (fromEnd)
{
for (s = slotNum - 1; s >= 0; s--)
{
if (CanPutItemIntoSlot(item, s, ignoreSlotTypes))
return s;
}
}
else
{
for (s = 0; s < slotNum; s++)
{
if (CanPutItemIntoSlot(item, s, ignoreSlotTypes))
return s;
}
}
return -1;
}
InventoryItemObject Inventory::GetItemInSlot(int index)
{
if (index >= slotNum)
return NULL;
InventoryItemObject item = slotItem[index];
return item;
}
bool Inventory::CanPutItemIntoSlot(InventoryItemObject item, int index, bool ignoreSlotTypes)
{
if (!GetSlotFree(index))
return false;
if (!ignoreSlotTypes && !item.CanPutIntoSlotType(slotType[index]))
return false;
return true;
}
bool Inventory::AddItem(InventoryItemObject item, int index)
{
if (!GetSlotFree(index))
return false;
slotItem[index] = item;
item.inventoryParent = this;
item.inventorySlot = index;
OnInventoryChanged();
return true;
}
bool Inventory::RemoveItem(InventoryItemObject item)
{
int index = GetSlotByItem(item);
if (index == -1)
return false;
slotItem[index] = NULL;
item.inventoryParent = NULL;
item.inventorySlot = -1;
OnInventoryChanged();
return true;
}
string Inventory::GetStringForVar(string varName, int optional_OnlySlot)
{
InventoryItemObject item;
string result;
if (optional_OnlySlot >= 0)
{
item = slotItem[optional_OnlySlot];
if (item && item.controller)
{
result = item.controller.IIController_GetStringForVar(varName);
if (result != "")
return result;
}
}
else
{
for (int i = 0; i < slotNum; i++)
{
item = slotItem[i];
if (item && item.controller)
{
result = item.controller.IIController_GetStringForVar(varName);
if (result != "")
return result;
}
}
}
return "";
}
int Inventory::GetIntForVar(string varName, int optional_OnlySlot)
{
InventoryItemObject item;
int result;
if (optional_OnlySlot >= 0)
{
item = slotItem[optional_OnlySlot];
if (item && item.controller)
{
result = item.controller.IIController_GetIntForVar(varName);
if (result != 0)
return result;
}
}
else
{
for (int i = 0; i < slotNum; i++)
{
item = slotItem[i];
if (item && item.controller)
{
result = item.controller.IIController_GetIntForVar(varName);
if (result != 0)
return result;
}
}
}
return 0;
}
float Inventory::GetFloatForVar(string varName, int optional_OnlySlot)
{
InventoryItemObject item;
float result;
if (optional_OnlySlot >= 0)
{
item = slotItem[optional_OnlySlot];
if (item && item.controller)
{
result = item.controller.IIController_GetFloatForVar(varName);
if (result != 0)
return result;
}
}
else
{
for (int i = 0; i < slotNum; i++)
{
item = slotItem[i];
if (item && item.controller)
{
result = item.controller.IIController_GetFloatForVar(varName);
if (result != 0)
return result;
}
}
}
return 0;
}
bool Inventory::GetBoolForVar(string varName, int optional_OnlySlot)
{
InventoryItemObject item;
bool result;
if (optional_OnlySlot >= 0)
{
item = slotItem[optional_OnlySlot];
if (item && item.controller)
{
result = item.controller.IIController_GetBoolForVar(varName);
if (result)
return result;
}
}
else
{
for (int i = 0; i < slotNum; i++)
{
item = slotItem[i];
if (item && item.controller)
{
result = item.controller.IIController_GetBoolForVar(varName);
if (result)
return result;
}
}
}
return false;
}
vector Inventory::GetVectorForVar(string varName, int optional_OnlySlot)
{
InventoryItemObject item;
vector result;
if (optional_OnlySlot >= 0)
{
item = slotItem[optional_OnlySlot];
if (item && item.controller)
{
result = item.controller.IIController_GetVectorForVar(varName);
if (result != ZeroVec)
return result;
}
}
else
{
for (int i = 0; i < slotNum; i++)
{
item = slotItem[i];
if (item && item.controller)
{
result = item.controller.IIController_GetVectorForVar(varName);
if (result != ZeroVec)
return result;
}
}
}
return ZeroVec;
}
void Inventory::ItemsOnEvent(string eventName)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEvent(eventName);
}
}
void Inventory::ItemsOnEventWithForce(string eventName, vector pos, vector force)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEventWithForce(eventName, pos, force);
}
}
void Inventory::ItemsOnEventWithInt(string eventName, int input)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEventWithInt(eventName, input);
}
}
void Inventory::ItemsOnEventWithFloat(string eventName, float input)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEventWithFloat(eventName, input);
}
}
void Inventory::ItemsOnEventWithVector(string eventName, vector input)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEventWithVector(eventName, input);
}
}
void Inventory::ItemsOnEventWithString(string eventName, string input)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEventWithString(eventName, input);
}
}
void Inventory::ItemsOnEventWithEntity(string eventName, _entity ent)
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemEventWithEntity(eventName, ent);
}
}
void Inventory::ItemsOnFrame()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
{
if (item.GetShouldDelete())
MPSafe_DeleteInventoryItemObject(item);
else
item.OnItemFrame();
}
}
}
void MPSafe_DeleteInventoryItemObject(InventoryItemObject item)
{
if (g_Game.IsClient())
return;
local InventoryItemObject invItem = item;
string replaceCFG = invItem.delayReplaceCFG;
if (replaceCFG != "")
{
Inventory replaceCFGOwner = invItem.inventoryParent;
int replaceCFGOwnerSlot = invItem.inventorySlot;
vector replaceCFGOwnerMat[4], replaceCFGOwnerLinVel, replaceCFGOwnerAngVel;
MatrixIdentity(replaceCFGOwnerMat);
local Object_InventoryItem itemWld = NULL;
if (invItem.worldID > 0)
itemWld = (Object_InventoryItem)FindEntityByID(g_Game.CurrentWorld, invItem.worldID);
if (itemWld)
{
GetMatrix4(itemWld, replaceCFGOwnerMat);
replaceCFGOwnerLinVel = GetVelocity(itemWld);
replaceCFGOwnerAngVel = dBodyGetAngularVelocity(itemWld);
}
itemWld = SpawnInventoryItemObject(replaceCFG, replaceCFGOwnerMat[3], NULL, -1, true);
}
if (g_Game.IsMultiplayer())
{
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
netPlayer.RP_DeleteInventoryItem(invItem.GetItemID(), -1, false );
}
else
{
delete invItem;
UniversalClassEvent("Item_Delete", invItem);
}
if (replaceCFG != "")
{
if (itemWld)
{
SetMatrix(itemWld, replaceCFGOwnerMat);
SetVelocity(itemWld, replaceCFGOwnerLinVel);
dBodySetAngularVelocity(itemWld, replaceCFGOwnerAngVel);
if (replaceCFGOwner)
{
if (g_Game.IsMultiplayer())
{
NetPlayerTKOM myNetPlayer = g_Game.GetLocalNetPlayerTKOM();
myNetPlayer.RP_MoveToInventory(replaceCFGOwner.parentEntID, replaceCFGOwner.indexInParent, replaceCFGOwnerSlot, itemWld.GetID(), true, false);
}
else
MoveToInventory(replaceCFGOwner.parentEntID, replaceCFGOwner.indexInParent, replaceCFGOwnerSlot, itemWld.GetID(), true);
}
}
}
}
Inventory GetInventoryByIDAndIndex(int id, int index)
{
if (id <= 0)
return NULL;
_entity ent = FindEntityByID(g_Game.CurrentWorld, id);
if (!ent)
return NULL;
if (IsInherited(ent, Type("Object_BuildingBlock")))
{
Object_BuildingBlock bblock = (Object_BuildingBlock)ent;
if (!bblock.inventory)
return NULL;
return bblock.inventory;
}
if (IsInherited(ent, Type("Vehicle_Handler")))
{
Vehicle_Handler vehicle = (Vehicle_Handler)ent;
Inventory inventory = vehicle.storage.inventories[index];
return inventory;
}
return NULL;
}
void MoveToOtherInventory(int id, int invIndex, int invItemIndex, int newID, int newInvIndex, int newSlot, bool ignoreSlotTypes)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
{
Print(String("GAMEOBJECTSIMPL.H - MOVETOOTHERINVENTORY: Cannot find inventory by ID " + itoa(id) + " and index " + itoa(invIndex) + "!"));
return;
}
Inventory newInventory = GetInventoryByIDAndIndex(newID, newInvIndex);
if (!newInventory)
{
Print(String("GAMEOBJECTSIMPL.H - MOVETOOTHERINVENTORY: Cannot find 2nd inventory by ID " + itoa(id) + " and index " + itoa(invIndex) + "!"));
return;
}
InventoryItemObject invItem = inventory.slotItem[invItemIndex];
if (!invItem)
{
Print(String("GAMEOBJECTSIMPL.H - MOVETOOTHERINVENTORY: Inventory item storage at index " + itoa(invItemIndex) + " does not exist!"));
return;
}
invItem.MoveToInventory(newInventory, newSlot, ignoreSlotTypes);
}
void MoveWithinInventory(int id, int invIndex, int invItemIndex, int newSlot, bool ignoreSlotTypes)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
{
Print(String("GAMEOBJECTSIMPL.H - MOVEWITHININVENTORY: Cannot find inventory by ID " + itoa(id) + " and index " + itoa(invIndex) + "!"));
return;
}
InventoryItemObject invItem = inventory.slotItem[invItemIndex];
if (!invItem)
{
Print(String("GAMEOBJECTSIMPL.H - MOVEWITHININVENTORY: Inventory item storage at index " + itoa(invItemIndex) + " does not exist!"));
return;
}
invItem.MoveWithinInventory(inventory, newSlot, ignoreSlotTypes);
}
int MoveToWorld(int id, int invIndex, int invItemIndex, int worldItemID, int grabUnitID, vector invItemMat[4])
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
{
Print(String("GAMEOBJECTSIMPL.H - MOVETOWORLD: Cannot find inventory by ID " + itoa(id) + " and index " + itoa(invIndex) + "!"));
return -1;
}
InventoryItemObject invItem = inventory.slotItem[invItemIndex];
if (!invItem)
{
Print(String("GAMEOBJECTSIMPL.H - MOVETOWORLD: Inventory item storage at index " + itoa(invItemIndex) + " does not exist!"));
return -1;
}
if (g_Game.IsClient())
invItem.MoveItemToWorldClient(worldItemID);
else
{
vector rndAng = Vector(frand(-15, 15), frand(-15, 15), frand(-15, 15));
Object_InventoryItem invItemEnt = (Object_InventoryItem)invItem.MoveItemToWorld(invItemMat, invItemMat[0] * frand(10, 20), rndAng);
worldItemID = invItemEnt.GetID();
}
if (grabUnitID != -1 && worldItemID != -1)
{
Vehicle_Handler myUnit = NULL;
if (grabUnitID > 0)
myUnit = (Vehicle_Handler)FindEntityByID(g_Game.CurrentWorld, grabUnitID);
if (myUnit)
myUnit.CallCustomEventWithInt("GRAB", worldItemID);
}
return worldItemID;
}
int MoveToInventory(int id, int invIndex, int slot, int itmID, bool ignoreSlotTypes)
{
Inventory inventory = GetInventoryByIDAndIndex(id, invIndex);
if (!inventory)
{
Print(String("GAMEOBJECTSIMPL.H - MOVETOINVENTORY: Cannot find inventory by ID " + itoa(id) + " and index " + itoa(invIndex) + "!"));
return -1;
}
if (g_Game.IsClient())
{
InventoryItemObject invItem = Global_GetInventoryItemByID(itmID);
if (!invItem)
Print(String("GAMEOBJECTSIMPL.H - MOVETOINVENTORY: Cannot find inventory item by ID " + itoa(itmID) + "!!!"));
else
invItem.MoveToInventory(inventory, slot, ignoreSlotTypes);
}
else
{
Object_InventoryItem invItemEnt = (Object_InventoryItem)FindEntityByID(g_Game.CurrentWorld, itmID);
invItemEnt.MoveToInventory(inventory, slot, ignoreSlotTypes);
itmID = invItemEnt.storage.GetItemID();
}
return itmID;
}
void Inventory::ItemsOnPostFrame()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemPostFrame();
}
}
void Inventory::ItemsOnSimulate()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.OnItemSimulate();
}
}
void Inventory::LoadItemScripts()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.LoadCustomScript(item.itemScript);
}
}
void Inventory::DeleteItemScripts()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.DeleteCustomScript();
}
}
void Inventory::RestoreItemIDs()
{
for (int i = 0; i < slotNum; i++)
{
InventoryItemObject item = slotItem[i];
if (item)
item.RestoreInvItemID();
}
}
InventoryItemObject Inventory::SpawnStoredItemObject(int itemID, int ownerSlot, string title, string desc, string image, string script, string config, string mdlPath, string rmpPath, string fxPath, float mass, string validSlotsStr, int genInt, float genFloat, vector genVec, string genStr)
{
InventoryItemObject invItemStorage = new InventoryItemObject();
invItemStorage.SetItemID(itemID);
invItemStorage.configFile = config;
invItemStorage.fxPath = fxPath;
invItemStorage.modelPath = mdlPath;
invItemStorage.remapPath = rmpPath;
invItemStorage.modelMass = mass;
invItemStorage.itemTitle = title;
invItemStorage.itemDesc = desc;
invItemStorage.itemImage = image;
invItemStorage.itemScript = script;
invItemStorage.ParseValidSlotTypesFromString(validSlotsStr);
invItemStorage.GenInt = genInt;
invItemStorage.GenFloat = genFloat;
invItemStorage.GenVec = genVec;
invItemStorage.SetGenString(genStr);
bool canAdd = CanPutItemIntoSlot(invItemStorage, ownerSlot, true);
if (!canAdd)
{
delete invItemStorage;
invItemStorage = NULL;
}
else
{
invItemStorage.LoadCustomScript(invItemStorage.itemScript);
invItemStorage.MoveToInventory(this, ownerSlot, true);
}
return invItemStorage;
}
//----------------------------------------------------------
void VehicleObject::DeleteInventoriesItemsScripts()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.DeleteItemScripts();
}
}
void VehicleObject::LoadInventoriesItemsScripts()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.LoadItemScripts();
}
}
void VehicleObject::RestoreInventoriesItemsIDs()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.RestoreItemIDs();
}
}
void VehicleObject::DestroyInventories()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
delete inventory;
inventories[inv] = NULL;
inventories_partNum[inv] = -1;
}
}
Inventory VehicleObject::FindInventoryByName(string invName)
{
if (invName == "")
return NULL;
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory && inventory.name == invName)
return inventory;
}
return NULL;
}
Inventory VehicleObject::FindInventoryByPartNum(int pNum)
{
if (pNum < 0 || pNum >= parts_num)
return NULL;
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory && inventories_partNum[inv] == pNum)
return inventory;
}
return NULL;
}
bool VehicleObject::CreateInventory(int index, string invName, int partNum, string layout, string hiText, string hiImg, int numSlots, string slotTypes[])
{
if (index >= INVENTORY_PEROBJECT_MAX)
{
CallError("VehicleObject::CreateInventory()", "Cannot create new inventory '" + invName + "' for VehicleObject, index " + itoa(index) + " over max of " + itoa(INVENTORY_PEROBJECT_MAX));
return false;
}
if (invName == "")
{
CallError("VehicleObject::CreateInventory()", "Cannot create inventory with no name! Check config..");
return false;
}
if (FindInventoryByName(invName))
{
CallError("VehicleObject::CreateInventory()", "Inventory titled '" + invName + "' already in list! Check config..");
return false;
}
inventories[index] = new Inventory(invName, this, index, Store_ID, layout, hiText, hiImg, numSlots, slotTypes);
inventories_partNum[index] = partNum;
if (inventoriesNum < index + 1)
inventoriesNum = index + 1;
return true;
}
void VehicleObject::InventoriesOnEvent(string eventName)
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnEvent(eventName);
}
}
void VehicleObject::InventoriesOnEventWithInt(string eventName, int input)
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnEventWithInt(eventName, input);
}
}
void VehicleObject::InventoriesOnEventWithEntity(string eventName, _entity ent)
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnEventWithEntity(eventName, ent);
}
}
void VehicleObject::InventoriesOnEventWithForce(string eventName, vector pos, vector force)
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnEventWithForce(eventName, pos, force);
}
}
void VehicleObject::InventoriesOnEventWithFloat(string eventName, float input)
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnEventWithFloat(eventName, input);
}
}
void VehicleObject::InventoriesOnFrame()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnFrame();
}
}
void VehicleObject::InventoriesOnPostFrame()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnPostFrame();
}
}
void VehicleObject::InventoriesOnSimulate()
{
for (int inv = 0; inv < inventoriesNum; inv++)
{
Inventory inventory = inventories[inv];
if (inventory)
inventory.ItemsOnSimulate();
}
}
void ProxyLoadCustomScript(InventoryItemObject item, string scriptPath)
{
ScriptModule temp_smodule = NULL;
InventoryItemController temp_controller = NULL;
//Print(String("LoadCustomScript: " + scriptPath));
if (scriptPath != "")
{
temp_smodule = LoadScriptEx(g_Game.Script, scriptPath, SCRIPT_STATICMEMORYSIZE_DEFAULT, false);
ScriptMemorySize_LogModuleSize(temp_smodule, scriptPath);
temp_controller = NULL;
if(temp_smodule)
{
temp_smodule.CallFunction(NULL, "CreateController", temp_controller, NULL); //this sets value to controller variable
}
else
Print(String("INVENTORYITEMOBJECT LOADCUSTOMSCRIPT: Could not load script '" + scriptPath + "'..."));
if(temp_smodule && !temp_controller)
{
temp_smodule.Release();
temp_smodule = NULL;
Print(String("INVENTORYITEMOBJECT LOADCUSTOMSCRIPT: Could not create controller instance in script '" + scriptPath + "'..."));
}
if (temp_controller)
temp_controller.IIController_Init(item);
}
item.smodule = temp_smodule;
item.controller = temp_controller;
}
//----------------------------------------------------------
void BuildingBlockObject::~BuildingBlockObject()
{
if (inventory && inventory.classParent == this)
delete inventory;
inventory = NULL;
}
//----------------------------------------------------------
void InventoryItemObject::DeleteCustomScript()
{
if (controller) {
controller.IIController_Exit(this);
delete controller; //destroy before destroying module!
}
if (smodule)
smodule.Release();
controller = NULL;
smodule = NULL;
}
void InventoryItemObject::LoadCustomScript(string scriptToLoad)
{
DeleteCustomScript();
// Must load through proxy function to avoid crash
ProxyLoadCustomScript(this, scriptToLoad);
}
bool InventoryItemObject::CanPutIntoSlotType(string type)
{
if (type == "")
return true;
for (int i = 0; i < validSlotTypesNum; i++)
{
if (type == validSlotTypes[i])
return true;
}
return false;
}
void InventoryItemObject::ClearValidSlotTypes()
{
for (int i = 0; i < INVENTORY_VALIDSLOTS_MAX; i++)
{
validSlotTypes[i] = "";
}
validSlotTypesNum = 0;
}
void InventoryItemObject::AddValidSlotType(string type)
{
if (validSlotTypesNum >= INVENTORY_VALIDSLOTS_MAX)
{
CallError("InventoryItemObject::AddValidSlotType()", "Cannot add new valid slot type, reached maximum of " + itoa(INVENTORY_VALIDSLOTS_MAX) + "!");
return;
}
validSlotTypes[validSlotTypesNum] = type;
validSlotTypesNum++;
}
void InventoryItemObject::SetValidSlotTypes(string types[], int num)
{
ClearValidSlotTypes();
for (int i = 0; i < num; i++)
{
AddValidSlotType(types[i]);
}
}
void InventoryItemObject::ParseValidSlotTypesFromString(string slotTypesStr)
{
string tokens[INVENTORY_VALIDSLOTS_MAX];
int numTokens = ParseString(slotTypesStr, tokens);
SetValidSlotTypes(tokens, numTokens);
}
string InventoryItemObject::WriteValidSlotTypesToString()
{
string result = "";
if (validSlotTypesNum > 1)
result = tostr(34);
for (int i = 0; i < validSlotTypesNum; i++) {
if (validSlotTypesNum <= i + 1)
result += validSlotTypes[i];
else
result += validSlotTypes[i] + " ";
}
if (validSlotTypesNum > 1)
result += tostr(34);
return result;
}
void InventoryItemObject::RemoveFromInventory()
{
if (inventoryParent)
{
int oldSlot = inventorySlot;
Inventory oldInventory = inventoryParent;
UniversalClassEvent("Item_RemoveFromInventory", this);
inventoryParent.RemoveItem(this);
if (controller)
controller.IIController_OnRemoveFromInventory(this, oldInventory, oldSlot);
}
}
bool InventoryItemObject::MoveWithinInventory(Inventory inv, int newSlot, bool ignoreSlotTypes)
{
if (inv.CanPutItemIntoSlot(this, newSlot, ignoreSlotTypes))
{
int oldSlot = inventorySlot;
inv.RemoveItem(this);
inv.AddItem(this, newSlot);
worldID = -1;
UniversalClassEvent("Item_BeforeMoveWithinInventory", this);
if (controller)
controller.IIController_OnMoveWithinInventory(this, inv, newSlot, oldSlot);
UniversalClassEvent("Item_AfterMoveWithinInventory", this);
return true;
}
return false;
}
bool InventoryItemObject::MoveToInventory(Inventory inv, int slot, bool ignoreSlotTypes)
{
if (inv.CanPutItemIntoSlot(this, slot, ignoreSlotTypes))
{
RemoveFromInventory();
inv.AddItem(this, slot);
UniversalClassEvent("Item_MoveToInventory", this);
worldID = -1;
if (controller)
controller.IIController_OnMoveToInventory(this, inv, slot);
return true;
}
return false;
}
TKOM_Entity InventoryItemObject::MoveItemToWorld(vector mat[4], vector velLin, vector velAng)
{
RemoveFromInventory();
bool networkEntity = GetNetworkEntityDef(NETWORK_USEDEFAULT, "Object_InventoryItem");
Object_InventoryItem ent = new Object_InventoryItem(mpID, mat[0], mat[1], mat[2], mat[3], modelPath, remapPath, fxPath, modelMass, networkEntity);
ent.SetSceneID(TKOMHighestEntID + 1);
SetVelocity(ent, velLin);
dBodySetAngularVelocity(ent, velAng);
worldID = ent.GetID();
if (controller)
controller.IIController_OnMoveItemToWorld(this, ent);
UniversalClassEvent("Item_MoveToWorld", this);
return ent;
}
TKOM_Entity InventoryItemObject::MoveItemToWorldClient(int wldItmID)
{
RemoveFromInventory();
bool networkEntity = GetNetworkEntityDef(NETWORK_USEDEFAULT, "Object_InventoryItem");
Object_InventoryItem ent = (Object_InventoryItem)FindEntityByID(g_Game.CurrentWorld, wldItmID);
worldID = wldItmID;
if (controller)
controller.IIController_OnMoveItemToWorld(this, ent);
UniversalClassEvent("Item_MoveToWorld", this);
return ent;
}
bool InventoryItemObject::GetCanRemoveFromInventory(Inventory inv, int slot)
{
if (GetShouldDelete())
return false;
if (controller)
return controller.IIController_GetCanRemoveFromInventory(this, inv, slot);
return true;
}
bool InventoryItemObject::GetCanMoveToInventory(Inventory inv, int slot)
{
if (GetShouldDelete())
return false;
if (controller)
return controller.IIController_GetCanMoveToInventory(this, inv, slot);
return true;
}
bool InventoryItemObject::GetCanMoveWithinInventory(Inventory inv, int newSlot, int oldSlot)
{
if (GetShouldDelete())
return false;
if (controller)
return controller.IIController_GetCanMoveWithinInventory(this, inv, newSlot, oldSlot);
return true;
}
bool InventoryItemObject::GetCanMoveToWorld()
{
if (GetShouldDelete())
return false;
if (controller)
return controller.IIController_GetCanMoveItemToWorld(this);
return true;
}
void InventoryItemObject::OnItemEvent(string eventName)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEvent(eventName);
}
void InventoryItemObject::OnItemEventWithForce(string eventName, vector pos, vector force)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEventWithForce(eventName, pos, force);
}
void InventoryItemObject::OnItemEventWithInt(string eventName, int input)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEventWithInt(eventName, input);
}
void InventoryItemObject::OnItemEventWithFloat(string eventName, float input)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEventWithFloat(eventName, input);
}
void InventoryItemObject::OnItemEventWithVector(string eventName, vector input)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEventWithVector(eventName, input);
}
void InventoryItemObject::OnItemEventWithString(string eventName, string input)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEventWithString(eventName, input);
}
void InventoryItemObject::OnItemEventWithEntity(string eventName, _entity ent)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnEventWithEntity(eventName, ent);
}
void InventoryItemObject::OnItemFrame()
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnFrm();
}
void InventoryItemObject::OnItemPostFrame()
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnPFrm();
}
void InventoryItemObject::OnItemSimulate()
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnSim();
}
void InventoryItemObject::OnItemInWater(WaterZone water, int extra)
{
if (GetShouldDelete())
return;
if (controller)
controller.IIController_OnItemInWater(water, extra);
}
int InventoryItemObject::FillInventoryOptions(string options[], CharacterObject caller)
{
if (controller)
return controller.IIController_FillInventoryOptions(options, caller);
return 0;
}
void InventoryItemObject::OnInventoryOption(int option, CharacterObject caller)
{
if (GetShouldDelete())
return;
if (!controller)
return;
if (g_Game.IsMultiplayer())
{
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
netPlayer.RP_InventoryItemOption(GetItemID(), caller.Store_ID, option, false);
}
else
{
controller.IIController_OnInventoryOption(option, caller);
UniversalClassEvent("Item_InventoryOption " + itoa(option), this);
}
}
void InventoryItemObject::OnInventoryEvent(string eventName, CharacterObject caller)
{
if (GetShouldDelete())
return;
if (!controller)
return;
if (g_Game.IsMultiplayer())
{
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
int id = 0;
if (caller)
id = caller.Store_ID;
netPlayer.RP_InventoryItemEvent(GetItemID(), id, eventName, false);
}
else
{
controller.IIController_OnInventoryEvent(eventName, caller);
UniversalClassEvent("Item_InventoryEvent " + eventName, this);
}
}
void InventoryItemObject::SynchGenInt()
{
if (!g_Game.IsMultiplayer())
return;
if (GetShouldDelete())
return;
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
if (mpGenInt != GenInt)
{
mpGenInt = GenInt;
netPlayer.RP_UpdateInventoryItem_GenInt(GetItemID(), GenInt, false );
}
}
void InventoryItemObject::SynchGenFloat()
{
if (!g_Game.IsMultiplayer())
return;
if (GetShouldDelete())
return;
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
if (mpGenFloat != GenFloat)
{
mpGenFloat = GenFloat;
netPlayer.RP_UpdateInventoryItem_GenFloat(GetItemID(), GenFloat, false );
}
}
void InventoryItemObject::SynchGenVec()
{
if (!g_Game.IsMultiplayer())
return;
if (GetShouldDelete())
return;
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
if (mpGenVec != GenVec)
{
mpGenVec = GenVec;
netPlayer.RP_UpdateInventoryItem_GenVec(GetItemID(), GenVec, false );
}
}
void InventoryItemObject::SynchGenString()
{
if (!g_Game.IsMultiplayer())
return;
if (GetShouldDelete())
return;
NetPlayerTKOM netPlayer = g_Game.GetLocalNetPlayerTKOM();
if (mpGenString != GenString)
{
mpGenString = GenString;
netPlayer.RP_UpdateInventoryItem_GenString(GetItemID(), GenString, false );
}
}
int Global_GetHighestInvItemID()
{
/*int result = -1;
for (int i = 0; i < Global_InvItems_EntityNum; i++) {
InventoryItemObject itm = Global_InvItems_List[i];
int myID = itm.GetItemID();
if (myID > result)
result = myID;
}
return result;*/
return Global_HighestInvItemID;
}
InventoryItemObject Global_GetInventoryItemByID(int id)
{
for (int i = 0; i < Global_InvItems_EntityNum; i++) {
InventoryItemObject itm = Global_InvItems_List[i];
int myID = itm.GetItemID();
if (myID == id)
return itm;
}
return NULL;
}
void InventoryItemObject::CreateID()
{
mpID = Global_GetHighestInvItemID() + 1;
if (Global_HighestInvItemID < mpID)
Global_HighestInvItemID = mpID;
}
void InventoryItemObject::SetItemID(int id)
{
mpID = id;
if (Global_HighestInvItemID < mpID)
Global_HighestInvItemID = mpID;
}
int InventoryItemObject::GetItemID()
{
return mpID;
}
//----------------------------------------------------------
void Object_InventoryItem::DeleteStorage()
{
if (!storage)
return;
MPSafe_DeleteInventoryItemObject(storage);
storage = NULL;
DelayDelete();
}
//----------------------------------------------------------
void VehicleObject::OnAfterLoad()
{
for (int i = 0; i < inventoriesNum; i++)
{
Inventory inventory = inventories[i];
if (inventory)
inventory.SetParent(this, Store_ID, i);
}
}
void Location::OnAfterLoad()
{
for (local int i = 0; i < vehiclesCount; i++)
{
VehicleObject vehicle = vehicles[i];
if (vehicle)
vehicle.OnAfterLoad();
}
}
//----------------------------------------------------------
bool GUI3DWidgetHandler::IsServer()
{
return g_Game.IsServer();
}
bool GUI3DWidgetHandler::IsClient()
{
return g_Game.IsClient();
}
bool GUI3DWidgetHandler::IsMultiplayer()
{
return g_Game.IsMultiplayer();
}
void GUI3DWidgetHandler::RP_OnClick(widget w, int x, int y, int button, bool pressedState, bool isRemoteCall)
{
bool isCallToServer = owner.IsCallToServer(isRemoteCall);
bool isCallToClients = owner.IsCallToClients(isRemoteCall);
if( owner.IsCallToLocal(isRemoteCall) )
{
if (pressedState && w && w.GetTypeName() == "ButtonWidget")
{
ButtonWidget wButton = (ButtonWidget)w;
wButton.SetState(pressedState);
}
UniversalClassWithWidgetEvent("OnClick", this, w, x, y, button);
//HandleWidgetClick(w);
MPSafe_OnClick(w, x, y, button);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = owner.RPCall(RPC_3DGUIHANDLER_EVENT);
adapter.WriteIntAsUByte(id);
adapter.WriteIntAsUByte(GUI3DEVENT_CLICK);
adapter.WriteString(GetWidgetPath(w));
clamp x<-32768, 32768>;
clamp y<-32768, 32768>;
adapter.WriteIntAsHalf(x);
adapter.WriteIntAsHalf(y);
adapter.WriteIntAsByte(button);
adapter.WriteBool(pressedState);
}
}
}
void GUI3DWidgetHandler::RP_OnMouseEnter(widget w, int x, int y, bool isRemoteCall)
{
bool isCallToServer = owner.IsCallToServer(isRemoteCall);
bool isCallToClients = owner.IsCallToClients(isRemoteCall);
if( owner.IsCallToLocal(isRemoteCall) )
{
UniversalClassWithWidgetEvent("OnMouseEnter", this, w, x, y, -1);
MPSafe_OnMouseEnter(w, x, y);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = owner.RPCall(RPC_3DGUIHANDLER_EVENT);
adapter.WriteIntAsUByte(id);
adapter.WriteIntAsUByte(GUI3DEVENT_MOUSEENTER);
adapter.WriteString(GetWidgetPath(w));
clamp x<-32768, 32768>;
clamp y<-32768, 32768>;
adapter.WriteIntAsHalf(x);
adapter.WriteIntAsHalf(y);
}
}
}
void GUI3DWidgetHandler::RP_OnMouseLeave(widget w, int x, int y, bool isRemoteCall)
{
bool isCallToServer = owner.IsCallToServer(isRemoteCall);
bool isCallToClients = owner.IsCallToClients(isRemoteCall);
if( owner.IsCallToLocal(isRemoteCall) )
{
UniversalClassWithWidgetEvent("OnMouseLeave", this, w, x, y, -1);
MPSafe_OnMouseLeave(w, x, y);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = owner.RPCall(RPC_3DGUIHANDLER_EVENT);
adapter.WriteIntAsUByte(id);
adapter.WriteIntAsUByte(GUI3DEVENT_MOUSELEAVE);
adapter.WriteString(GetWidgetPath(w));
clamp x<-32768, 32768>;
clamp y<-32768, 32768>;
adapter.WriteIntAsHalf(x);
adapter.WriteIntAsHalf(y);
}
}
}
void GUI3DWidgetHandler::RP_OnMouseButtonDown(widget w, int x, int y, int button, bool isRemoteCall)
{
bool isCallToServer = owner.IsCallToServer(isRemoteCall);
bool isCallToClients = owner.IsCallToClients(isRemoteCall);
if( owner.IsCallToLocal(isRemoteCall) )
{
UniversalClassWithWidgetEvent("OnMouseButtonDown", this, w, x, y, button);
MPSafe_OnMouseButtonDown(w, x, y, button);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = owner.RPCall(RPC_3DGUIHANDLER_EVENT);
adapter.WriteIntAsUByte(id);
adapter.WriteIntAsUByte(GUI3DEVENT_MOUSEDOWN);
adapter.WriteString(GetWidgetPath(w));
clamp x<-32768, 32768>;
clamp y<-32768, 32768>;
adapter.WriteIntAsHalf(x);
adapter.WriteIntAsHalf(y);
adapter.WriteIntAsByte(button);
}
}
}
void GUI3DWidgetHandler::RP_OnMouseButtonUp(widget w, int x, int y, int button, bool isRemoteCall)
{
bool isCallToServer = owner.IsCallToServer(isRemoteCall);
bool isCallToClients = owner.IsCallToClients(isRemoteCall);
if( owner.IsCallToLocal(isRemoteCall) )
{
UniversalClassWithWidgetEvent("OnMouseButtonUp", this, w, x, y, button);
MPSafe_OnMouseButtonUp(w, x, y, button);
}
if( isCallToServer || isCallToClients )
{
if( g_Game.CanRPCall() )
{
//if local computer is client: send message to server
//if local computer is server: send the same message to all clients
PacketOutputAdapter adapter = owner.RPCall(RPC_3DGUIHANDLER_EVENT);
adapter.WriteIntAsUByte(id);
adapter.WriteIntAsUByte(GUI3DEVENT_MOUSEUP);
adapter.WriteString(GetWidgetPath(w));
clamp x<-32768, 32768>;
clamp y<-32768, 32768>;
adapter.WriteIntAsHalf(x);
adapter.WriteIntAsHalf(y);
adapter.WriteIntAsByte(button);
}
}
}
bool GUI3DWidgetHandler::OnRPC(int proc, PacketInputAdapter input)
{
if (proc != RPC_3DGUIHANDLER_EVENT)
return false;
int evtType = input.ReadIntAsUByte();
string wPath = input.ReadString();
widget w = NULL;
if (rootWidget && wPath != "")
w = FindWidget(rootWidget, wPath);
int x = input.ReadIntAsHalf();
int y = input.ReadIntAsHalf();
int button;
switch(evtType)
{
case GUI3DEVENT_CLICK:
{
/*if (w)
Print(String("GUI3DEVENT_CLICK - " + w.GetName()));
else
Print(String("GUI3DEVENT_CLICK - NULL"));*/
button = input.ReadIntAsByte();
bool buttonPressed = input.ReadBool();
if (w)
RP_OnClick(w, x, y, button, buttonPressed, true);
break;
}
case GUI3DEVENT_MOUSEENTER:
{
/*if (w)
Print(String("GUI3DEVENT_MOUSEENTER - " + w.GetName()));
else
Print(String("GUI3DEVENT_MOUSEENTER - NULL"));*/
if (w)
RP_OnMouseEnter(w, x, y, true);
break;
}
case GUI3DEVENT_MOUSELEAVE:
{
/*if (w)
Print(String("GUI3DEVENT_MOUSELEAVE - " + w.GetName()));
else
Print(String("GUI3DEVENT_MOUSELEAVE - NULL"));*/
if (w)
RP_OnMouseLeave(w, x, y, true);
break;
}
case GUI3DEVENT_MOUSEDOWN:
{
/*if (w)
Print(String("GUI3DEVENT_MOUSEDOWN - " + w.GetName()));
else
Print(String("GUI3DEVENT_MOUSEDOWN - NULL"));*/
button = input.ReadIntAsByte();
if (w)
RP_OnMouseButtonDown(w, x, y, button, true);
break;
}
case GUI3DEVENT_MOUSEUP:
{
/*if (w)
Print(String("GUI3DEVENT_MOUSEUP - " + w.GetName()));
else
Print(String("GUI3DEVENT_MOUSEUP - NULL"));*/
button = input.ReadIntAsByte();
if (w)
RP_OnMouseButtonUp(w, x, y, button, true);
break;
}
}
return true;
}
//----------------------------------------------------------
// Game definitions
#include "scripts/Campaign/GameDefsImpl.h"
// Conversation class
#include "scripts/Campaign/ConversationImpl.h"
/***********************************************************************************************************************************************************
* BUILDING BLOCK CONFIG
***********************************************************************************************************************************************************/
MODEL "obj/structures/mars_base/3dprinter.xob"
MASS 96
BUILD 60
FXTYPE "scripts/entities/configs/fx/part_small.cfg"
SCRIPT "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Machine_3DPrinter.h"
SLOT "0 0 24" "-90 0 90" "Create" true true true false
SLOT "0 0 0" "0 0 -180" "TOPSURFACE" true true false false
IMAGE "gui/textures/printer3dhud/mars_base/3dprinter"
ACTIVATE "3D PRINTER MENU"
INVENTORY "3DPInv" "gui/layouts/inventory_3dprinter_creative.layout" "#tkom_useaction_openinv" "gui/textures/inventory_open" 12
INVENTORY_SLOT 0 "3DPData"
INVENTORY_SLOT 1 "3DPData"
INVENTORY_SLOT 2 "3DPData"
INVENTORY_SLOT 3 "3DPData"
INVENTORY_SLOT 4 "3DPData"
INVENTORY_SLOT 5 "3DPData"
INVENTORY_SLOT 6 "3DPData"
INVENTORY_SLOT 7 "3DPData"
INVENTORY_SLOT 8 "3DPData"
INVENTORY_SLOT 9 "3DPData"
INVENTORY_SLOT 10 "3DPData"
INVENTORY_SLOT 11 "3DPData"
CONST_INFO "Uses:" "2"
INVENTORY_ITEM_NEW 0 "Scripts/Entities/Configs/InventoryItems/3DP_Discs/disc_001.cfg"
UI_TITLE "3D Printer (Creative Mode)"
UI_DESC "Used to print various objects and building components such as walls, windows, barrels and so on."
UI_FILTER "Machines Printers" "'#tkom_3D_filter_machines' '#tkom_3D_filter_printers'"
DDISC_NO 1
/***********************************************************************************************************************************************************
***********************************************************************************************************************************************************//****************************************************************************
* ATMOSPHERIC PROCESSOR CONTROLLER
***************************************************************************/
const bool DEBUG_PRINTRESOURCEPOOLS = false;
const float ATMOPROC_AMOUNTPERSEC = 0.5;
const float ATMOPROC_GATHERDELAY = 2;
const float ATMOPROC_GATHERPOOLMAX = 5;
const float ATMOPROC_GATHEREFFICIENTAMOUNT = 500;
const float ATMOPROC_SNDRANDOMPITCHTIMESECS = 60;
const float ATMOPROC_SND_FADETIME = 2;
const float ATMOPROC_CANMINECHECKTIME = 1;
const string ATMOPROC_PTCPATH = "particle/atmoproc_windin.ptc";
class Machine_AtmoProcController extends BuildingBlockController
{
float gatherDelay;
Location myLocation;
ParticleEmitter ptcEmit;
float atmoprocSnd;
float atmoprocSndPtchTime;
float cannotGather_checkTime;
#include "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Common/MachinePowerDisplay_FuncsVars.h"
float ResourcesGatherPool[RESOURCE_MAXTYPES];
void ClearPooledResources()
{
for (int g = 0; g < RESOURCE_MAXTYPES; g++)
{
ResourcesGatherPool[g] = 0;
}
}
bool GetAnyViableResources(Object_BuildingBlock owner)
{
vector myPos = GetOrigin(owner);
int secX = myLocation.GetSectorAtPosX(myPos[0]);
int secY = myLocation.GetSectorAtPosY(myPos[1]);
for (int r = 0; r < myLocation.ResourcesNum; r++)
{
Resource_Base rscEnt = myLocation.Resources[r];
if (rscEnt.areaType != RESOURCE_AREATYPE_ATMOSPHERIC)
continue;
if (rscEnt.GetSectorAmount(secX, secY) > 0)
return true;
}
return false;
}
//----------------------------------------------------------
bool IsSlotDistanceBased(Object_BuildingBlock owner, int slot)
{
if (owner.Slots_Types[slot] == "RscBrlIn" || owner.Slots_Types[slot] == "RscBrlOut")
return true;
else
return false;
}
//----------------------------------------------------------
void BBController_OnToDynamic(Object_BuildingBlock owner)
{
ClearPooledResources();
}
//----------------------------------------------------------
void BBController_OnToStatic(Object_BuildingBlock owner)
{
ClearPooledResources();
}
//----------------------------------------------------------
void BBController_Init(Object_BuildingBlock owner)
{
SetPowerParameters(1200, 30);
#include "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Common/MachinePowerDisplay_Init.c"
ClearPooledResources();
gatherDelay = 0;
atmoprocSnd = 0;
atmoprocSndPtchTime = frand(0, ATMOPROC_SNDRANDOMPITCHTIMESECS);
myLocation = g_Campaign.currentLocation;
ptcEmit = NULL;
cannotGather_checkTime = ATMOPROC_CANMINECHECKTIME;
}
//----------------------------------------------------------
void BBController_OnPFrm(Object_BuildingBlock owner)
{
#include "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Common/MachinePowerDisplay_OnPFrm_1.c"
bool noProcess = false;
// If not static or location has no resources
if (owner.IsDynamic || myLocation.ResourcesNum <= 0)
noProcess = true;
if (!owner.GetBuilt())
noProcess = true;
if (!IsClient() && !noProcess)
{
cannotGather_checkTime += ftime;
if (cannotGather_checkTime >= ATMOPROC_CANMINECHECKTIME)
{
cannotGather_checkTime = 0;
#include "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Common/MachinePowerDisplay_OnPFrm_2.c"
}
}
#include "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Common/MachinePowerDisplay_OnPFrm_3.c"
if (inUseTime >= POWER_MINREQUIRED_SECS)
inUseTime = 0;
atmoprocSndPtchTime += ftime;
if (atmoprocSndPtchTime >= ATMOPROC_SNDRANDOMPITCHTIMESECS)
atmoprocSndPtchTime -= ATMOPROC_SNDRANDOMPITCHTIMESECS;
// Handle particle effect
if (noProcess)
{
if (ptcEmit)
{
ptcEmit.Pause();
if (ptcEmit.IsFinished())
{
ptcEmit.QueueDelete();
ptcEmit = NULL;
}
}
}
else
{
vector atmoProcMat[4];
GetMatrix4(owner, atmoProcMat);
if (!ptcEmit)
{
ptcEmit = new ParticleEmitter;
ptcEmit.priority = PTCEMT_PRIORITY_MED;
SetMatrix(ptcEmit, atmoProcMat);
ptcEmit.Play(ATMOPROC_PTCPATH);
}
else
{
SetMatrix(ptcEmit, atmoProcMat);
ptcEmit.UnPause();
}
}
// Handle sound
if (!noProcess)
atmoprocSnd += ftime / ATMOPROC_SND_FADETIME;
else
atmoprocSnd -= ftime / ATMOPROC_SND_FADETIME;
clamp atmoprocSnd<0, 1>;
if (atmoprocSnd > 0)
{
float sndPitchRnd = sin(atmoprocSndPtchTime / ATMOPROC_SNDRANDOMPITCHTIMESECS * 360 * DEG2RAD) * 0.05;
owner.PlaySnd(PART_SOUNDS_EXTCHNL1, "effects/machines/atmoproc_hum", SFX_3D, atmoprocSnd * 0.7, atmoprocSnd * 0.3 + 0.5 + sndPitchRnd);
owner.PlaySnd(PART_SOUNDS_EXTCHNL2, "effects/machines/atmoproc_fan", SFX_3D, atmoprocSnd * 0.7, atmoprocSnd * 0.3 + 0.5);
}
else
{
owner.StopSnd(PART_SOUNDS_EXTCHNL1);
owner.StopSnd(PART_SOUNDS_EXTCHNL2);
}
if (noProcess)
return;
if (IsClient())
return;
Resource_Base rscEnt;
vector myPos = GetOrigin(owner);
int secX = myLocation.GetSectorAtPosX(myPos[0]);
int secY = myLocation.GetSectorAtPosY(myPos[1]);
float getRscAmtF;
gatherDelay += ftime;
for (int g = 0; g < myLocation.ResourcesNum; g++)
{
rscEnt = myLocation.Resources[g];
if (rscEnt.areaType != RESOURCE_AREATYPE_ATMOSPHERIC)
continue;
getRscAmtF = ResourcesGatherPool[g];
getRscAmtF += ftime * ATMOPROC_AMOUNTPERSEC * rscEnt.GetExtractScale(ATMOPROC_GATHEREFFICIENTAMOUNT, secX, secY, 0, 1);
clamp getRscAmtF<0, ATMOPROC_GATHERPOOLMAX>;
ResourcesGatherPool[g] = getRscAmtF;
}
// Return if we have not passed the gather delay
if (gatherDelay < ATMOPROC_GATHERDELAY)
return;
gatherDelay -= ATMOPROC_GATHERDELAY;
if (DEBUG_PRINTRESOURCEPOOLS)
{
Print(String("ATMOSPERIC PROCESSOR (ID: " + itoa(owner.GetID()) + ")"));
for (g = 0; g < myLocation.ResourcesNum; g++)
{
rscEnt = myLocation.Resources[g];
if (rscEnt.areaType != RESOURCE_AREATYPE_ATMOSPHERIC)
continue;
Print(String(rscEnt.name + ": " + itoa(rscEnt.GetSectorAmount(secX, secY)) + " - " + ftoa(ResourcesGatherPool[g])));
}
Print("");
}
Object_BuildingBlock rscBarrel = NULL;
Object_BuildingBlock rscBarrels[BUILDBLOCK_SLOTSMAX];
int rscBarrelsNum = 0;
for (int i = 0; i < BUILDBLOCK_SLOTSMAX; i++)
{
rscBarrels[i] = NULL;
}
// Get a list of barrels currently plugged into the machine, that still have space
for (i = 0; i < owner.SlotsNum; i++)
{
int entId = owner.Slots_LinkEntID[i];
if (entId <= 0)
continue;
if (owner.Slots_Types[i] != "RscBrlIn")
continue;
TKOM_Entity bblockBase = GetTKOMEntityByID(entId);
if (IsInherited(bblockBase, Type("Object_BuildingBlock"))) {
rscBarrel = (Object_BuildingBlock)bblockBase;
for (int n = 0; n < rscBarrel.ResStoreNum; n++)
{
if (rscBarrel.ResStore_Amount[n] >= rscBarrel.ResStore_MaxAmount[n])
continue;
rscBarrels[rscBarrelsNum] = rscBarrel;
rscBarrelsNum++;
break;
}
}
}
for (int r = 0; r < myLocation.ResourcesNum; r++)
{
rscEnt = myLocation.Resources[r];
if (rscEnt.areaType != RESOURCE_AREATYPE_ATMOSPHERIC)
continue;
int curGottenRscAmt = floor(ResourcesGatherPool[r]);
if (curGottenRscAmt <= 0) // No resource to extract yet, skip
continue;
int maxGottenRscAmt = rscEnt.GetSectorAmount(secX, secY);
clamp curGottenRscAmt<0, maxGottenRscAmt>;
if (curGottenRscAmt <= 0) // No resource in this sector, skip
continue;
getRscAmtF = ResourcesGatherPool[r] - fsum(curGottenRscAmt);
clamp getRscAmtF<0, ATMOPROC_GATHERPOOLMAX>;
ResourcesGatherPool[r] = getRscAmtF;
int totalToRemoveFromSector = curGottenRscAmt;
int rscStoreSlot;
// First try to find barrels that already have the resource, and try to fill them
for (i = 0; i < rscBarrelsNum; i++)
{
// Gained resource amount distributed, so skip remaining barrels
if (curGottenRscAmt <= 0)
break;
rscBarrel = rscBarrels[i];
rscStoreSlot = rscBarrel.GetResourceStorageSlotForResource(rscEnt.name, true);
if (rscStoreSlot == -1)
continue;
// Add resource to the resource storage slot and return how much is left from the input amount
curGottenRscAmt = rscBarrel.AddResource(rscStoreSlot, curGottenRscAmt, rscEnt.name);
// Gained resource amount distributed, so skip remaining barrels
if (curGottenRscAmt <= 0)
break;
}
// Now fill any barrels with what's left of the resource
for (i = 0; i < rscBarrelsNum; i++)
{
// Gained resource amount distributed, so skip remaining barrels
if (curGottenRscAmt <= 0)
break;
rscBarrel = rscBarrels[i];
rscStoreSlot = rscBarrel.GetResourceStorageSlotForResource(rscEnt.name, false);
if (rscStoreSlot == -1)
continue;
// Add resource to the resource storage slot and return how much is left from the input amount
curGottenRscAmt = rscBarrel.AddResource(rscStoreSlot, curGottenRscAmt, rscEnt.name);
}
// Don't remove atmosphere from the sector :)
totalToRemoveFromSector -= curGottenRscAmt;
rscEnt.TakeAmountFromSector(totalToRemoveFromSector, secX, secY, true);
//rscEnt.MPSynchSector(secX, secY);
}
}
//----------------------------------------------------------
void BBController_Exit(Object_BuildingBlock owner)
{
#include "scripts/Entities/Controllers/TakeMeToMars/BuildingBlocks/Common/MachinePowerDisplay_Exit.c"
if (ptcEmit)
ptcEmit.QueueDelete();
ptcEmit = NULL;
}
//----------------------------------------------------------
int NeedNetUpdate()
{
int error = Power_NeedNetUpdate();
return error;
}
void OnNetUpdate( PacketOutputAdapter output )
{
Power_OnNetUpdate(output);
}
bool OnNetMessage( PacketInputAdapter input )
{
Power_OnNetMessage(input);
return true;
}
}
//-----------------------------------------------------------------------------------
BuildingBlockController CreateController()
{
return new Machine_AtmoProcController;
}
/****************************************************************************
***************************************************************************//****************************************************************************
* INVENTORY ITEM ENTITY DEFINITION
***************************************************************************/
class Object_InventoryItem extends TKOM_Entity
{
InventoryItemObject storage;
bool delayDelete;
int delayNetTickDelete;
int FXIndex;
float ImpactNextTime;
ParticleEmitter ptc_emit;
Sound_Point fx_snd[PART_SOUNDS_MAX];
Vehicle_Light l_Ent; // Pointer to the light entity
// Water splash function
#include "scripts/global/watersplashfuncs.h"
bool IsThermalActive();
void DelayDelete();
void OnDelete()
{
if (FFCamHandlerRef)
FFCamHandlerRef.OnDeleteTKOMEntity(this);
}
bool CanGrab()
{
if (delayDelete)
return false;
return true;
}
bool MoveToInventory(Inventory inv, int slot, bool ignoreSlotTypes)
{
if (!delayDelete && storage.MoveToInventory(inv, slot, ignoreSlotTypes))
{
DelayDelete();
return true;
}
return false;
}
void DeleteStorage(); // Defined in GameObjectsImpl.h
void DeleteSelf();
void UpdateStorageWorldData()
{
if (delayDelete)
return;
if (!storage)
return;
storage.worldID = GetID();
GetMatrix4(this, storage.worldMatrix);
if (noUpdate)
{
storage.worldVelocity = noUpdate_velLin;
storage.worldAngVelocity = noUpdate_velAng;
}
else
{
storage.worldVelocity = GetVelocity(this);
storage.worldAngVelocity = dBodyGetAngularVelocity(this);
}
}
// Adds a light entity to the part if it has none
bool AddLight(vector locPos, vector locAng, int type, int flags, float radius, vector color, float cone)
{
if (!l_Ent) {
if (IsThermalActive())
return true;
else {
l_Ent = new Vehicle_Light(type, flags, radius, color, cone);
if (l_Ent) {
AddChild(this, l_Ent, -1);
SetOrigin(l_Ent, locPos);
SetAngles(l_Ent, locAng);
return true;
} else
Print("OBJECT_INVENTORYITEM: AddLight() - Could not create Vehicle_Light!");
}
} else {
if (IsThermalActive()) {
delete l_Ent;
l_Ent = NULL;
return true;
} else {
SetOrigin(l_Ent, locPos);
SetAngles(l_Ent, locAng);
return true;
}
}
return false;
}
void RemoveLight()
{
if (l_Ent) {
delete l_Ent;
l_Ent = NULL;
}
}
bool HasLight()
{
if (l_Ent)
return true;
else
return false;
}
// Plays a particle effect on the inventory item, creates it if it does not exist
void PlayPTC(string ptcStr)
{
if (!ptc_emit) {
ptc_emit = new ParticleEmitter;
AddChild(this, ptc_emit, -1);
SetOrigin(ptc_emit, ZeroVec);
SetAngles(ptc_emit, ZeroVec);
ptc_emit.Play(ptcStr);
} else {
if (ptc_emit.ParticleToPlay == ptcStr) {
if (ptc_emit.PtcPaused)
ptc_emit.UnPause();
} else
ptc_emit.Play(ptcStr);
}
}
// Pauses the attached particle effect
void PausePTC()
{
if (ptc_emit)
ptc_emit.Pause();
}
// Lerps the value on the attached particle effect
void LerpPTC(float val, int param)
{
if (ptc_emit)
ptc_emit.Lerp(val, param);
}
// Returns the amount of active particles in the attached particle effect
int GetActivePTCCount()
{
if (ptc_emit)
return GetParticleCount(ptc_emit);
else
return 0;
}
// Deletes the attached particle effect
void DeletePTC()
{
if (ptc_emit) {
RemoveChild(this, ptc_emit);
ptc_emit.QueueDelete();
ptc_emit = NULL;
}
}
// Stops a playing sound on the part
void StopSnd(int sndIndex)
{
if (fx_snd[sndIndex]) {
/*Sound_Point sndPt = fx_snd[sndIndex];
if (sndPt.attached)
RemoveChild(this, sndPt);*/
delete fx_snd[sndIndex];
fx_snd[sndIndex] = NULL;
}
}
// Stops all sounds
void DeleteSnds()
{
for (int i = 0; i < PART_SOUNDS_MAX; i++) {
StopSnd(i);
}
}
// Plays a sound on the part
void PlaySnd(int sndIndex, string sshader, int flags, float volume, float freq)
{
if (Snd_Global_Vol > 0 && Snd_Global_Freq > 0) { // Don't play sounds if global modulators are null
Sound_Point sndPt = NULL;
if (!fx_snd[sndIndex]) {
sndPt = new Sound_Point(GetOrigin(this), false, sshader, flags, volume, freq);
if (sndPt.snd_handle == -1)
Print(String("OBJECT_INVENTORYITEM - PlaySnd: Could not play sound '" + sshader + "'!!!"));
else
fx_snd[sndIndex] = sndPt;
}
if (fx_snd[sndIndex]) {
sndPt = fx_snd[sndIndex];
sndPt.snd_vol = volume;
sndPt.snd_freq = freq;
if (sndPt.snd_shader != sshader) {
StopSnd(sndIndex);
PlaySnd(sndIndex, sshader, flags, volume, freq);
}
}
}
}
// Plays a sound at a location
void PlaySndAt(vector pos, string sshader, int flags, float volume, float freq)
{
if (Snd_Global_Vol > 0 && Snd_Global_Freq > 0) { // Don't play sounds if global modulators are null
Sound_Point sndPt = new Sound_Point(pos, true, sshader, flags, volume, freq);
if (sndPt.snd_handle == -1)
Print(String("OBJECT_INVENTORYITEM - PlaySndAt: Could not play sound '" + sshader + "'!!!"));
}
}
// Returns an empty sound channel slot
int GetFreeSoundChannel()
{
int result = -1;
for (int i = 0; i < PART_SOUNDS_MAX; i++) {
if (!fx_snd[i]) {
result = i;
i = PART_SOUNDS_MAX;
}
}
return result;
}
// Updates sounds and their positions
void UpdateSounds()
{
if (!noUpdate) {
for (int i = 0; i < PART_SOUNDS_MAX; i++) {
if (fx_snd[i]) {
Sound_Point sndPt = fx_snd[i];
if (sndPt.snd_handle == -1)
StopSnd(i);
else
SetOrigin(sndPt, GetOrigin(this));
}
}
} else
DeleteSnds();
}
//! MULTIPLAYER: See comment in GameEntity class
void OnNetObjectInitSend( PacketOutputAdapter output )
{
output.WriteInt( GetID() );
output.WriteInt(storage.GetItemID());
output.WriteString(storage.configFile);
output.WriteStaticString(storage.fxPath);
output.WriteStaticString(storage.modelPath);
output.WriteStaticString(storage.remapPath);
output.WriteFloat(storage.modelMass);
output.WriteStaticString(storage.itemTitle);
output.WriteString(storage.itemDesc);
output.WriteString(storage.itemImage);
output.WriteString(storage.itemScript);
//output.WriteString(storage.WriteValidSlotTypesToString());
output.WriteInt(storage.validSlotTypesNum);
for(int vs = 0; vs < storage.validSlotTypesNum; vs++)
{
output.WriteString(storage.validSlotTypes[vs]);
}
output.WriteInt(storage.GenInt);
output.WriteFloat(storage.GenFloat);
output.WriteVector(storage.GenVec);
output.WriteString(storage.GenString);
}
void OnNetObjectInitReceived( PacketInputAdapter input )
{
SetSceneID(input.ReadInt());
int vs;
if (!storage)
{
InventoryItemObject invItem = new InventoryItemObject();
invItem.SetItemID(input.ReadInt());
invItem.configFile = input.ReadString();
invItem.fxPath = input.ReadStaticString();
invItem.modelPath = input.ReadStaticString();
invItem.remapPath = input.ReadStaticString();
invItem.modelMass = input.ReadFloat();
invItem.itemTitle = input.ReadStaticString();
invItem.itemDesc = input.ReadString();
invItem.itemImage = input.ReadString();
invItem.itemScript = input.ReadString();
//invItem.ParseValidSlotTypesFromString(input.ReadString());
invItem.validSlotTypesNum = input.ReadInt();
for(vs = 0; vs < invItem.validSlotTypesNum; vs++)
{
invItem.validSlotTypes[vs] = input.ReadString();
}
invItem.GenInt = input.ReadInt();
invItem.GenFloat = input.ReadFloat();
invItem.GenVec = input.ReadVector();
invItem.SetGenString(input.ReadString());
invItem.worldID = GetID();
invItem.LoadCustomScript(invItem.itemScript);
storage = invItem;
}
else
{
input.ReadInt();
input.ReadString();
input.ReadStaticString();
input.ReadStaticString();
input.ReadStaticString();
input.ReadFloat();
input.ReadStaticString();
input.ReadString();
input.ReadString();
input.ReadString();
//input.ReadString();
int vs2 = input.ReadInt();
for(vs = 0; vs < vs2; vs++)
{
input.ReadString();
}
input.ReadInt();
input.ReadFloat();
input.ReadVector();
input.ReadString();
}
}
void Object_InventoryItem(int storageID, vector mat0, vector mat1, vector mat2, vector mat3, string mdl, string rmp, string fx, float mass, bool netEnt);
void ~Object_InventoryItem();
void UpdateAtmosphericDrag()
{
dBodySetDamping(this, CurrentWorldAirFriction, CurrentWorldAirFriction);
}
event private void EOnSimulate(_entity other, float dt)
{
if (!noUpdate && !delayDelete)
{
preContactVel = GetVelocity(this);
preContactAngVel = dBodyGetAngularVelocity(this);
storage.OnItemSimulate();
}
}
event private void EOnPostFrame(_entity other, int extra)
{
if (!noUpdate && !delayDelete)
storage.OnItemPostFrame();
}
event private void EOnFrame(_entity other, int extra)
{
if (!delayDelete)
{
if (!storage)
CallError("Object_InventoryItem(" + itoa(GetID()) + ")::EOnFrame()", "Inventory item has NULL storage!!!");
UpdateSounds();
UpdateAtmosphericDrag();
if (IsThermalActive() && HasLight())
RemoveLight();
if (storage && storage.GetShouldDelete())
DeleteStorage();
else
{
if (!noUpdate)
storage.OnItemFrame();
}
}
if (delayDelete)
DeleteSelf();
}
private void EOnTouch(_entity other, int extra)
{
ctype gameEntType = Type("WaterZone");
if (IsInherited(other, gameEntType))
{
storage.OnItemInWater((WaterZone)other, extra);
}
}
private void EOnContact(_entity other, Contact extra)
{
if (!noUpdate && extra.Impulse > 0) {
CheckTreeContact(this, other, extra);
vector mins, maxs;
GetBoundBox(this, mins, maxs);
float PartDensity = GetObjectMass(this) / VectorLength(maxs - mins);
float ContactVel = VectorLength(dBodyGetVelocityAt(this, extra.Position));
if (dBodyIsSet(other))
ContactVel = VectorLength(dBodyGetVelocityAt(other, extra.Position) - dBodyGetVelocityAt(this, extra.Position));
float ContactImpulse = extra.Impulse * fabs(1 / PartDensity) + ContactVel * 0.5;
int iLvl = 0;
if (ContactImpulse >= PART_IMPACT_HEAVY)
iLvl = 4;
else {
if (ContactImpulse >= PART_IMPACT_MEDIUM)
iLvl = 3;
else {
if (ContactImpulse >= PART_IMPACT_LIGHT)
iLvl = 2;
else {
if (ContactImpulse >= PART_IMPACT_SCRAPE)
iLvl = 1;
}
}
}
Vehicle_FX fxEnt = NULL;
if (FXIndex != -1)
fxEnt = Vehicle_FXList[FXIndex];
if (fxEnt && GetMissionTime(1) >= ImpactNextTime && iLvl > 0) {
string iPtc = "";
string iSnd = "";
string iSndFar = "";
float iVol = 1;
float iVolFar = 1;
float iDistFar = 3200;
vector mat[4];
if (iLvl == 4) {
ImpactNextTime = GetMissionTime(1) + frand(fxEnt.FX_Lng_Contact_Hvy * 0.9, fxEnt.FX_Lng_Contact_Hvy * 1.1);
iSnd = fxEnt.FX_Snd_Contact_Hvy;
iSndFar = fxEnt.FX_Snd_ContactFar_Hvy;
iVol = fxEnt.FX_Vol_Contact_Hvy;
iVolFar = fxEnt.FX_Vol_Contact_Hvy;
iPtc = fxEnt.FX_Ptc_Contact_Hvy;
iDistFar = fxEnt.FX_Dist_ContactFar_Hvy;
}
if (iLvl == 3) {
ImpactNextTime = GetMissionTime(1) + frand(fxEnt.FX_Lng_Contact_Med * 0.9, fxEnt.FX_Lng_Contact_Med * 1.1);
iSnd = fxEnt.FX_Snd_Contact_Med;
iSndFar = fxEnt.FX_Snd_ContactFar_Med;
iVol = fxEnt.FX_Vol_Contact_Med;
iVolFar = fxEnt.FX_Vol_Contact_Med;
iPtc = fxEnt.FX_Ptc_Contact_Med;
iDistFar = fxEnt.FX_Dist_ContactFar_Med;
}
if (iLvl == 2) {
ImpactNextTime = GetMissionTime(1) + frand(fxEnt.FX_Lng_Contact_Lgt * 0.9, fxEnt.FX_Lng_Contact_Lgt * 1.1);
iSnd = fxEnt.FX_Snd_Contact_Lgt;
iSndFar = fxEnt.FX_Snd_ContactFar_Lgt;
iVol = fxEnt.FX_Vol_Contact_Lgt;
iVolFar = fxEnt.FX_Vol_Contact_Lgt;
iPtc = fxEnt.FX_Ptc_Contact_Lgt;
iDistFar = fxEnt.FX_Dist_ContactFar_Lgt;
}
GetCamera(CurrentListenCam, mat);
float dist = VectorLength(GetOrigin(this) - mat[3]);
if (iLvl == 1) {
if (dist <= PART_SCRAPE_MAXDIST && GetMissionTime(1) > Part_LastScrape) {
if (ContactVel >= PART_SCRAPE_HEAVY) {
Part_LastScrape = GetMissionTime(1) + frand(fxEnt.FX_Lng_Scrape_Hvy * 0.9, fxEnt.FX_Lng_Scrape_Hvy * 1.1);
iSnd = fxEnt.FX_Snd_Scrape_Hvy;
iVol = fxEnt.FX_Vol_Scrape_Hvy;
iPtc = fxEnt.FX_Ptc_Scrape_Hvy;
} else {
if (ContactVel >= PART_SCRAPE_MEDIUM) {
Part_LastScrape = GetMissionTime(1) + frand(fxEnt.FX_Lng_Scrape_Med * 0.9, fxEnt.FX_Lng_Scrape_Med * 1.1);
iSnd = fxEnt.FX_Snd_Scrape_Med;
iVol = fxEnt.FX_Vol_Scrape_Med;
iPtc = fxEnt.FX_Ptc_Scrape_Med;
} else {
Part_LastScrape = GetMissionTime(1) + frand(fxEnt.FX_Lng_Scrape_Lgt * 0.9, fxEnt.FX_Lng_Scrape_Lgt * 1.1);
iSnd = fxEnt.FX_Snd_Scrape_Lgt;
iVol = fxEnt.FX_Vol_Scrape_Lgt;
iPtc = fxEnt.FX_Ptc_Scrape_Lgt;
}
}
}
}
GetMatrix4(this, mat);
if (iSnd != "" && dist < iDistFar)
PlaySndAt(mat[3], iSnd, SFX_ONCE|SFX_3D|SFX_DISCARDABLE, iVol, frand(0.9, 1.1));
if (iSndFar != "" && dist >= iDistFar)
PlaySndAt(mat[3], iSndFar, SFX_ONCE|SFX_3D|SFX_DISCARDABLE, iVolFar, frand(0.9, 1.1));
if (iPtc != "") {
vector up = extra.Normal;
vector forward = mat[0];
vector aside = up * forward;
VectorNormalize(aside);
forward = aside * up;
VectorNormalize(forward);
mat[0] = forward;
mat[1] = aside;
mat[2] = up;
mat[3] = extra.Position;
PlayParticleEffect(iPtc, mat, fxEnt.FX_Ptc_Priority);
}
}
}
}
}
/****************************************************************************
***************************************************************************/FILE ° addon.xml? ü ü more sector resources.txt; | | scripts campaign gameobjectsdecl.h· 2£ 2£ gameobjectsimpl.hé¦ D D entities configs buildingblocks printer3d printerbase.cfgôê ~ ~ controllers takemetomars buildingblocks machine_atmoprocessor.hrò ƒ) ƒ) object_inventoryitem.hõ €7 €7