diff -urN sourceold/AntiSpawnKill/AntiSpawnKill.vcxproj source/AntiSpawnKill/AntiSpawnKill.vcxproj
--- sourceold/AntiSpawnKill/AntiSpawnKill.vcxproj 2018-10-27 22:04:54.438400000 +1000
+++ source/AntiSpawnKill/AntiSpawnKill.vcxproj 2020-09-26 09:00:03.253003000 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/CTF/ctf.vcxproj source/CTF/ctf.vcxproj
--- sourceold/CTF/ctf.vcxproj 2018-10-27 22:04:54.445400000 +1000
+++ source/CTF/ctf.vcxproj 2020-09-26 09:00:03.254025700 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/CharacterRefund/CharacterRefund.vcxproj source/CharacterRefund/CharacterRefund.vcxproj
--- sourceold/CharacterRefund/CharacterRefund.vcxproj 2018-10-27 22:04:54.449400000 +1000
+++ source/CharacterRefund/CharacterRefund.vcxproj 2020-09-26 09:00:03.254025700 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/ExtraConsoleCommands/ExtraConsoleCommands.vcxproj source/ExtraConsoleCommands/ExtraConsoleCommands.vcxproj
--- sourceold/ExtraConsoleCommands/ExtraConsoleCommands.vcxproj 2018-10-27 22:04:54.455400000 +1000
+++ source/ExtraConsoleCommands/ExtraConsoleCommands.vcxproj 2020-09-26 09:00:03.255035400 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/FirstBlood/FirstBlood.vcxproj source/FirstBlood/FirstBlood.vcxproj
--- sourceold/FirstBlood/FirstBlood.vcxproj 2018-10-27 22:04:54.460400000 +1000
+++ source/FirstBlood/FirstBlood.vcxproj 2020-09-26 09:00:03.255035400 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/MemoryManager/MemoryManager.vcxproj source/MemoryManager/MemoryManager.vcxproj
--- sourceold/MemoryManager/MemoryManager.vcxproj 2018-10-27 22:04:54.620400000 +1000
+++ source/MemoryManager/MemoryManager.vcxproj 2020-09-26 09:00:03.260402700 +1000
@@ -28,7 +28,7 @@
DynamicLibrary
Unicode
true
- v110_xp
+ v110
DynamicLibrary
@@ -40,7 +40,7 @@
DynamicLibrary
Unicode
true
- v110_xp
+ v110
DynamicLibrary
@@ -134,6 +134,7 @@
false
true
true
+ 6.01
if defined RenPath (
@@ -186,6 +187,7 @@
Windows
$(OutDir)$(TargetName)$(TargetExt)
false
+ 6.01
@@ -225,6 +227,7 @@
false
true
$(TargetDir)$(TargetName).map
+ 6.01
if defined RenPath (
@@ -276,6 +279,7 @@
true
$(OutDir)$(TargetName)$(TargetExt)
false
+ 6.01
diff -urN sourceold/Mute/Mute.vcxproj source/Mute/Mute.vcxproj
--- sourceold/Mute/Mute.vcxproj 2018-10-27 22:04:54.636400000 +1000
+++ source/Mute/Mute.vcxproj 2020-09-26 09:00:03.260402700 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/NoPoints/NoPoints.vcxproj source/NoPoints/NoPoints.vcxproj
--- sourceold/NoPoints/NoPoints.vcxproj 2018-10-27 22:04:54.641400000 +1000
+++ source/NoPoints/NoPoints.vcxproj 2020-09-26 09:00:03.261400000 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/PointsDistribution/PointsDistribution.vcxproj source/PointsDistribution/PointsDistribution.vcxproj
--- sourceold/PointsDistribution/PointsDistribution.vcxproj 2018-10-27 22:04:54.652400000 +1000
+++ source/PointsDistribution/PointsDistribution.vcxproj 2020-09-26 09:00:03.262426400 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/Spectate/Spectate.vcxproj source/Spectate/Spectate.vcxproj
--- sourceold/Spectate/Spectate.vcxproj 2018-10-27 22:04:54.657400000 +1000
+++ source/Spectate/Spectate.vcxproj 2020-09-26 09:00:03.263394900 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/SuddenDeath/SuddenDeath.vcxproj source/SuddenDeath/SuddenDeath.vcxproj
--- sourceold/SuddenDeath/SuddenDeath.vcxproj 2018-10-27 22:04:54.663400000 +1000
+++ source/SuddenDeath/SuddenDeath.vcxproj 2020-09-26 09:00:03.263394900 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/bansystem/bansystem.vcxproj source/bansystem/bansystem.vcxproj
--- sourceold/bansystem/bansystem.vcxproj 2018-10-27 22:04:54.675400000 +1000
+++ source/bansystem/bansystem.vcxproj 2020-09-26 09:00:03.268381300 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/crates/crates.vcxproj source/crates/crates.vcxproj
--- sourceold/crates/crates.vcxproj 2018-10-27 22:04:54.685400000 +1000
+++ source/crates/crates.vcxproj 2020-09-26 09:00:03.269381100 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -108,6 +108,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -185,6 +186,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/example-plugin/example-plugin.vcxproj source/example-plugin/example-plugin.vcxproj
--- sourceold/example-plugin/example-plugin.vcxproj 2018-10-27 22:04:56.127400000 +1000
+++ source/example-plugin/example-plugin.vcxproj 2020-09-26 09:00:03.271374200 +1000
@@ -20,13 +20,13 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
MultiByte
true
- v110_xp
+ v110
@@ -93,6 +93,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
@@ -159,6 +160,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
diff -urN sourceold/randomstartingcredits/RandomStartingCredits.vcxproj source/randomstartingcredits/RandomStartingCredits.vcxproj
--- sourceold/randomstartingcredits/RandomStartingCredits.vcxproj 2018-10-27 22:04:56.159400000 +1000
+++ source/randomstartingcredits/RandomStartingCredits.vcxproj 2020-09-26 09:00:03.274365300 +1000
@@ -20,14 +20,14 @@
DynamicLibrary
MultiByte
false
- v110_xp
+ v110
DynamicLibrary
false
MultiByte
true
- v110_xp
+ v110
@@ -109,6 +109,7 @@
MachineX86
..\bin\release SSGM;..\bin\release
false
+ 6.01
if defined RenPath (
@@ -186,6 +187,7 @@
MachineX86
..\bin\debug SSGM;..\bin\debug
false
+ 6.01
if defined RenPath (
diff -urN sourceold/scripts/ArmedGameObj.h source/scripts/ArmedGameObj.h
--- sourceold/scripts/ArmedGameObj.h 2018-11-17 10:23:56.953600000 +1000
+++ source/scripts/ArmedGameObj.h 2020-09-10 09:08:27.944914000 +1000
@@ -39,6 +39,10 @@
virtual const Matrix3D &Get_Muzzle( int index = 0 );
void Start_Recoil( int muzzle_index,float recoil_scale,float recoil_time );
float Get_Weapon_Error( void ) { return Get_Definition().WeaponError; }
+ float Get_Weapon_Turn_Min(void) { return Get_Definition().WeaponTurnMin; }
+ float Get_Weapon_Turn_Max(void) { return Get_Definition().WeaponTurnMax; }
+ float Get_Weapon_Tilt_Min(void) { return Get_Definition().WeaponTiltMin; }
+ float Get_Weapon_Tilt_Max(void) { return Get_Definition().WeaponTiltMax; }
Vector3 Get_Targeting_Pos( void ) { return TargetingPos; }
virtual bool Set_Targeting( const Vector3 & pos, bool do_tilt = true );
virtual ArmedGameObj *As_ArmedGameObj( void ) { return this; }
diff -urN sourceold/scripts/ArmedGameObjDef.h source/scripts/ArmedGameObjDef.h
--- sourceold/scripts/ArmedGameObjDef.h 2018-11-17 10:23:56.954600000 +1000
+++ source/scripts/ArmedGameObjDef.h 2020-03-28 21:10:59.007874300 +1000
@@ -18,6 +18,8 @@
ArmedGameObjDef( void );
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
+ int Get_Weapon_Def_ID() const { return WeaponDefID; }
+ int Get_Secondary_Weapon_Def_ID() const { return SecondaryWeaponDefID; }
#ifdef DDBEDIT
virtual void Dump (FileClass &file);
#endif
diff -urN sourceold/scripts/AudibleSoundDefinitionClass.cpp source/scripts/AudibleSoundDefinitionClass.cpp
--- sourceold/scripts/AudibleSoundDefinitionClass.cpp 2018-11-17 10:23:56.956600000 +1000
+++ source/scripts/AudibleSoundDefinitionClass.cpp 2020-09-10 09:08:27.944914000 +1000
@@ -31,7 +31,7 @@
AudibleSoundDefinitionClass::AudibleSoundDefinitionClass() : m_Priority(0.5), m_Volume(1), m_VolumeRandomizer(0), m_Pan(0.5), m_LoopCount(1), m_VirtualChannel(0), m_DropoffRadius(40), m_MaxVolRadius(20), m_Is3DSound(true), m_Type(1), m_StartOffset(0), m_PitchFactor(1), m_PitchFactorRandomizer(0), m_LogicalType(0), m_LogicalNotifDelay(2.0), m_LogicalDropoffRadius(-1.0), m_CreateLogicalSound(false), m_SphereColor(0,0.75,0.75)
{
#ifdef PARAM_EDITING_ON
- NAMED_EDITABLE_PARAM(AudibleSoundDefinitionClass,ParameterClass::TYPE_FILENAME,m_Filename,"Filename");
+ NAMED_EDITABLE_PARAM(AudibleSoundDefinitionClass,ParameterClass::TYPE_SOUND_FILENAME,m_Filename,"Filename");
INT_EDITABLE_PARAM(AudibleSoundDefinitionClass,m_VirtualChannel,0,100);
NAMED_EDITABLE_PARAM(AudibleSoundDefinitionClass,ParameterClass::TYPE_FLOAT,m_DropoffRadius,"Drop-off Radius");
NAMED_EDITABLE_PARAM(AudibleSoundDefinitionClass,ParameterClass::TYPE_FLOAT,m_MaxVolRadius,"Max-Vol Radius");
diff -urN sourceold/scripts/BeaconGameObjDef.h source/scripts/BeaconGameObjDef.h
--- sourceold/scripts/BeaconGameObjDef.h 2018-11-17 10:23:56.961600000 +1000
+++ source/scripts/BeaconGameObjDef.h 2020-09-10 09:08:27.945919000 +1000
@@ -26,6 +26,7 @@
PersistClass* Create() const;
int Is_Nuke() const {return IsNuke;}
bool Requires_Silo() const {return RequiresSilo;}
+ int Get_Explosion_Obj_Def() const {return ExplosionObjDef;}
#ifdef DDBEDIT
virtual void Dump (FileClass &file);
#endif
diff -urN sourceold/scripts/BuildingGameObj.h source/scripts/BuildingGameObj.h
--- sourceold/scripts/BuildingGameObj.h 2018-11-17 10:23:56.965600000 +1000
+++ source/scripts/BuildingGameObj.h 2020-03-28 21:10:59.007874300 +1000
@@ -107,6 +107,7 @@
#endif
SCRIPTS_API void Find_Closest_Poly (const Vector3 &pos, float *distance2);
float Find_Closest_Poly(const Vector3 &pos) { float distance2; Find_Closest_Poly(pos,&distance2); return distance2; }
+ void Find_Closest_Poly(const Vector3& pos, float* distance2, Vector3* polyPos);
int Building_In_Range(const Vector3 &point, float range); //return 0 for no, 1 for yes and 2 for MCT in range
bool Is_In_Range_Coarse(const Vector3& point, float range_sq);
bool Cast_Ray(RayCollisionTestClass& raytest);
@@ -145,7 +146,7 @@
void Add_Aggregate(BuildingAggregateClass * aggregate);
void Remove_Aggregate(BuildingAggregateClass * aggregate);
void Add_Light(LightPhysClass * light);
- void Find_Closest_Poly_For_Model (RenderObjClass *model, const Vector3 &pos, float *distance2);
+ void Find_Closest_Poly_For_Model (RenderObjClass *model, const Vector3 &pos, float *distance2, Vector3* polyPos = NULL);
void Update_State(bool force_update = false);
void Enable_Alternate_Materials(RefMultiListClass & models, bool onoff);
void Enable_Alternate_Materials(RenderObjClass * model,bool onoff);
diff -urN sourceold/scripts/Defines.h source/scripts/Defines.h
--- sourceold/scripts/Defines.h 2018-11-17 10:23:56.993600000 +1000
+++ source/scripts/Defines.h 2020-09-26 09:00:03.275362600 +1000
@@ -30,6 +30,7 @@
#pragma warning(disable:4251)
#define WIN32_LEAN_AND_MEAN
+#define _WIN32_WINNT 0x0601
#define _USE_MATH_DEFINES
// breakpoint
diff -urN sourceold/scripts/Doxyfile source/scripts/Doxyfile
--- sourceold/scripts/Doxyfile 2018-11-17 10:23:57.001600000 +1000
+++ source/scripts/Doxyfile 2020-04-02 12:02:44.436401100 +1000
@@ -32,7 +32,7 @@
# This could be handy for archiving the generated documentation or
# if some version control system is used.
-PROJECT_NUMBER = 4.6
+PROJECT_NUMBER = 4.7
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.
diff -urN sourceold/scripts/HumanStateClass.h source/scripts/HumanStateClass.h
--- sourceold/scripts/HumanStateClass.h 2018-11-17 10:23:57.015600000 +1000
+++ source/scripts/HumanStateClass.h 2020-09-10 09:08:27.945919000 +1000
@@ -160,6 +160,7 @@
void Update_Recoil(WeaponClass * weapon);
void Begin_Jump( void );
void Complete_Jump( void );
+ void GetLegAndHoldStyle (int *leg_style,int *hold_style);
};
diff -urN sourceold/scripts/LineSegClass.cpp source/scripts/LineSegClass.cpp
--- sourceold/scripts/LineSegClass.cpp 2018-11-17 10:23:57.023600000 +1000
+++ source/scripts/LineSegClass.cpp 2020-09-10 09:08:27.946909600 +1000
@@ -34,6 +34,7 @@
Matrix3D::Transform_Vector(transform, object.P1, &P1);
DP = P1 - P0;
Matrix3D::Rotate_Vector(transform, object.Dir, &Dir);
+ Length = object.Length;
}
bool LineSegClass::Find_Intersection(const LineSegClass &other_line, Vector3 *p1, float *fraction1, Vector3 *p2, float *fraction2) const
diff -urN sourceold/scripts/ObjectLibraryManager.cpp source/scripts/ObjectLibraryManager.cpp
--- sourceold/scripts/ObjectLibraryManager.cpp 1970-01-01 10:00:00.000000000 +1000
+++ source/scripts/ObjectLibraryManager.cpp 2020-03-28 21:10:59.056743700 +1000
@@ -0,0 +1,31 @@
+#include "general.h"
+
+#include "ObjectLibraryManager.h"
+#include "DefinitionMgrClass.h"
+#include "Definition.h"
+PhysicalGameObj* ObjectLibraryManager::Create_Object
+ (const char* cPresetName)
+{
+ // const DefinitionClass* oDefinition = DefinitionMgrClass::Find_Typed_Definition (cPresetName, 12288, true);
+ DefinitionClass* oDefinition = DefinitionMgrClass::Find_Named_Definition (cPresetName, true);
+
+ StringClass oError;
+ if (!oDefinition || !oDefinition->Is_Valid_Config (oError))
+ return 0;
+
+ return (PhysicalGameObj *)oDefinition->Create();
+}
+
+
+
+PhysicalGameObj* ObjectLibraryManager::Create_Object
+ (uint32 uDefinitionID)
+{
+ DefinitionClass* oDefinition = DefinitionMgrClass::Find_Definition (uDefinitionID, true);
+
+ StringClass oError;
+ if (!oDefinition || !oDefinition->Is_Valid_Config (oError))
+ return 0;
+
+ return (PhysicalGameObj *)oDefinition->Create();
+}
diff -urN sourceold/scripts/ObjectLibraryManager.h source/scripts/ObjectLibraryManager.h
--- sourceold/scripts/ObjectLibraryManager.h 1970-01-01 10:00:00.000000000 +1000
+++ source/scripts/ObjectLibraryManager.h 2020-03-28 21:10:59.056743700 +1000
@@ -0,0 +1,16 @@
+#ifndef TT_INCLUDE__OBJECTLIBRARYMANAGER_H
+#define TT_INCLUDE__OBJECTLIBRARYMANAGER_H
+#include "Persist.h"
+class PhysicalGameObj;
+class ObjectLibraryManager
+{
+
+public:
+
+ static PhysicalGameObj* Create_Object (const char* cPresetName);
+ static PhysicalGameObj* Create_Object (uint32 uDefinitionID);
+
+};
+
+
+#endif
diff -urN sourceold/scripts/PhysicsSceneClass.h source/scripts/PhysicsSceneClass.h
--- sourceold/scripts/PhysicsSceneClass.h 2019-06-22 07:43:44.222400000 +1000
+++ source/scripts/PhysicsSceneClass.h 2020-03-28 21:10:59.011863900 +1000
@@ -393,10 +393,6 @@
static bool AllowCollisionFlags[NUM_COLLISION_FLAGS];
int DynamicPolyBudget;
int StaticPolyBudget;
-#ifdef TT_EXPORTS
- float mapStaticPolyBudget;
- float mapDynamicPolyBudget;
-#endif
RefMultiListClass ObjList;
RefMultiListClass StaticObjList;
RefMultiListClass StaticLightList;
@@ -417,5 +413,9 @@
#endif
friend class WW3D;
friend class VisOptimizationContextClass;
+#ifdef TT_EXPORTS
+ float mapStaticPolyBudget;
+ float mapDynamicPolyBudget;
+#endif
}; // 792, WIN: 700
#endif
diff -urN sourceold/scripts/RefineryGameObj.h source/scripts/RefineryGameObj.h
--- sourceold/scripts/RefineryGameObj.h 2018-11-17 10:23:57.068600000 +1000
+++ source/scripts/RefineryGameObj.h 2020-09-10 09:08:27.946909600 +1000
@@ -61,6 +61,7 @@
{
AllowHarvesterSpawn = true;
}
+ static float HarvesterDumpRate;
private:
void Load_Variables (ChunkLoadClass &cload);
HarvesterClass * Harvester;
@@ -75,6 +76,8 @@
AudibleSoundClass * MoneyTrickleSound;
bool AllowHarvesterSpawn;
ReferencerClass HarvesterVehicle;
+ float accumulatedDumpCredits;
+ float DumpRate;
}; // 2232, RH7 2252
diff -urN sourceold/scripts/RefineryGameObjDef.h source/scripts/RefineryGameObjDef.h
--- sourceold/scripts/RefineryGameObjDef.h 2018-11-17 10:23:57.068600000 +1000
+++ source/scripts/RefineryGameObjDef.h 2020-03-28 21:10:59.012889300 +1000
@@ -22,6 +22,8 @@
~RefineryGameObjDef (void);
uint32 Get_Class_ID (void) const;
PersistClass * Create (void) const;
+ float Get_Funds_Gathered() const { return FundsGathered; }
+ float Get_Funds_Distributed_Per_Sec() const { return FundsDistributedPerSec; }
bool Save (ChunkSaveClass &csave);
bool Load (ChunkLoadClass &cload);
const PersistFactoryClass & Get_Factory (void) const;
diff -urN sourceold/scripts/SmartGameObjDef.h source/scripts/SmartGameObjDef.h
--- sourceold/scripts/SmartGameObjDef.h 2018-11-17 10:23:57.086600000 +1000
+++ source/scripts/SmartGameObjDef.h 2020-09-10 09:08:27.947906000 +1000
@@ -26,6 +26,12 @@
virtual bool Save( ChunkSaveClass &csave );
virtual bool Load( ChunkLoadClass &cload );
bool Is_Stealthed() const {return IsStealthUnit;}
+ /* Modifies the sight range of the object. SightRange is used by AI code only. */
+ void Set_Sight_Range (const float range) { SightRange = range; }
+ float Get_Sight_Range() const {return SightRange;}
+ /* Modifies the sight arc of the object. SightArc is used by AI code only. */
+ void Set_Sight_Arc (const float arc) { SightArc = arc; }
+ float Get_Sight_Arc() const {return SightArc;}
#ifdef DDBEDIT
virtual void Dump (FileClass &file);
#endif
diff -urN sourceold/scripts/SoldierGameObj.h source/scripts/SoldierGameObj.h
--- sourceold/scripts/SoldierGameObj.h 2019-06-22 07:31:28.791400000 +1000
+++ source/scripts/SoldierGameObj.h 2020-09-10 09:08:27.947906000 +1000
@@ -202,6 +202,9 @@
bool Get_Use_Stock_Ghost_Behavior(){return useStockGhostBehavior;}
void Set_Override_Muzzle_Direction(bool override){OverrideMuzzleDirection = override; Set_Object_Dirty_Bit(BIT_RARE, true);};
bool Get_Override_Muzzle_Direction(){return OverrideMuzzleDirection;};
+ void Set_Bot_Tag(const char* tag) { botTag = tag; Set_Object_Dirty_Bit(BIT_RARE, true); }
+ const WideStringClass& Get_Bot_Tag() { return botTag; }
+ bool Is_Bot() { return botTag.Get_Length() > 0; }
virtual int Get_Contact_Surface_Type();
virtual float Get_Skeleton_Heigth( void );
virtual void Set_Skeleton_Height( float height );
@@ -288,6 +291,8 @@
float lastSkeletonWidth;
int overrideWeaponHoldStyleId;
bool enableHumanAnimOverride;
+ WideStringClass botTag;
+ int sight_bone;
TT_DEPRECATED("Do not use") int Check(void);
}; // size: 3404
diff -urN sourceold/scripts/SoundSceneObjClass.h source/scripts/SoundSceneObjClass.h
--- sourceold/scripts/SoundSceneObjClass.h 2018-10-27 22:04:56.326400000 +1000
+++ source/scripts/SoundSceneObjClass.h 2020-03-28 21:10:59.014855700 +1000
@@ -18,6 +18,9 @@
#include "audiocallback.h"
#include "Persist.h"
#include "Matrix3D.h"
+#if !defined(W3DVIEWER) && !defined(TTLE_EXPORTS)
+#include "HashTemplateClass.h"
+#endif
class SoundSceneClass;
class SoundCullObjClass;
class Sound3DClass;
@@ -28,6 +31,7 @@
class RenderObjClass;
const uint32 SOUND_OBJ_DEFAULT_ID = 0;
const uint32 SOUND_OBJ_START_ID = 1000000000;
+
class SoundSceneObjClass : public MultiListObjectClass, public PersistClass, public RefCountClass
{
public:
@@ -87,9 +91,23 @@
int m_AttachedBone; // 0030 0048
uint32 m_UserData; // 0034 004C
RefCountClass * m_UserObj; // 0038 0050
+
static uint32 m_NextAvailableID;
static DynamicVectorClass m_GlobalSoundList;
static CriticalSectionClass m_IDListMutex;
+
+ // Added by TT
+#if !defined(W3DVIEWER) && !defined(TTLE_EXPORTS)
+public:
+ static void Associate_Server_ID(SoundSceneObjClass* sound_obj, uint32 server_id);
+
+protected:
+ static HashTemplateClass m_ServerGlobalSoundList;
+ static HashTemplateClass m_ReversedServerGlobalSoundList;
+ static CriticalSectionClass m_ServerIDListMutex;
+
+ static bool Find_Server_Sound_Object(uint32 server_id_to_find, SoundSceneObjClass*& sound_obj);
+#endif
}; // 003C 0054
#endif
diff -urN sourceold/scripts/SysTimeClass.cpp source/scripts/SysTimeClass.cpp
--- sourceold/scripts/SysTimeClass.cpp 2018-11-17 10:23:57.099600000 +1000
+++ source/scripts/SysTimeClass.cpp 2020-09-10 09:08:27.948915200 +1000
@@ -32,7 +32,15 @@
this->Reset();
}
- return timeGetTime() - this->uTimeInit;
+ unsigned int u = timeGetTime();
+ if (u <= uTimeInit)
+ {
+ return uTimeInitNeg + u;
+ }
+ else
+ {
+ return u - uTimeInit;
+ }
}
diff -urN sourceold/scripts/TwiddlerClass.h source/scripts/TwiddlerClass.h
--- sourceold/scripts/TwiddlerClass.h 2018-11-17 10:23:57.112600000 +1000
+++ source/scripts/TwiddlerClass.h 2020-03-28 21:10:59.014855700 +1000
@@ -19,6 +19,7 @@
virtual DefinitionClass *Twiddle() const;
PersistClass *Create() const;
const PersistFactoryClass &Get_Factory() const;
+ const DynamicVectorClass& Get_Definition_List() { return m_DefinitionList; }
bool Save(ChunkSaveClass &csave);
bool Load(ChunkLoadClass &cload);
bool Save_Variables(ChunkSaveClass &csave);
diff -urN sourceold/scripts/Vector3.h source/scripts/Vector3.h
--- sourceold/scripts/Vector3.h 2018-11-17 10:23:57.113600000 +1000
+++ source/scripts/Vector3.h 2020-09-10 09:08:27.948915200 +1000
@@ -327,9 +327,11 @@
TT_INLINE static float Distance(const Vector3 &p1, const Vector3 &p2)
{
- Vector3 temp;
- temp = p1 - p2;
- return (temp.Length());
+ return (p1 - p2).Length();
+ }
+ TT_INLINE static float Distance_Squared(const Vector3 &p1, const Vector3 &p2)
+ {
+ return (p1 - p2).Length2();
}
TT_INLINE static void Lerp(const Vector3 &a, const Vector3 &b, float alpha,Vector3 *set_result)
{
diff -urN sourceold/scripts/VehicleGameObj.h source/scripts/VehicleGameObj.h
--- sourceold/scripts/VehicleGameObj.h 2019-06-22 07:31:28.793400000 +1000
+++ source/scripts/VehicleGameObj.h 2020-03-28 21:10:59.015853000 +1000
@@ -98,6 +98,7 @@
void Update_Damage_Meshes( void );
float Get_Squish_Velocity( void) { return Get_Definition().SquishVelocity; }
void Script_Enable_Transitions( bool enable ) { TransitionsEnabled = enable; Create_And_Destroy_Transitions(); }
+ bool Get_Transitions_Enabled ( void ) { return TransitionsEnabled; }
static void Set_Precision(void);
static bool Toggle_Target_Steering( void );
static void Set_Target_Steering( bool onoff );
diff -urN sourceold/scripts/WWAudioClass.h source/scripts/WWAudioClass.h
--- sourceold/scripts/WWAudioClass.h 2018-10-27 22:04:56.358400000 +1000
+++ source/scripts/WWAudioClass.h 2020-03-28 21:10:59.016850200 +1000
@@ -198,6 +198,10 @@
AudibleSoundClass * Create_Sound (int definition_id, RefCountClass *user_obj = NULL, uint32 user_data = 0, int classid_hint = CLASSID_3D);
AudibleSoundClass * Create_Sound (const char *def_name, RefCountClass *user_obj = NULL, uint32 user_data = 0, int classid_hint = CLASSID_3D);
SoundSceneObjClass * Find_Sound_Object (uint32 sound_obj_id);
+#if !defined(W3DVIEWER) && !defined(TTLE_EXPORTS)
+ SoundSceneObjClass* Find_Server_Sound_Object(uint32 server_sound_obj_id); // Added by TT
+ uint32 Get_New_Server_Sound_ID(); // Added by TT
+#endif
SoundSceneClass * Get_Sound_Scene (void) const { return m_SoundScene; }
bool Set_Cache_Size (int kbytes = DEF_CACHE_SIZE) { m_MaxCacheSize = (kbytes * 1024); }
int Get_Cache_Size (void) const { return m_MaxCacheSize / 1024; }
diff -urN sourceold/scripts/anticheat.ini source/scripts/anticheat.ini
--- sourceold/scripts/anticheat.ini 2018-11-17 10:23:37.857600000 +1000
+++ source/scripts/anticheat.ini 2020-09-26 08:59:57.386159600 +1000
@@ -134,3 +134,63 @@
185315cb0070e52ab9c89d95d06f05e5=C&C_Complex.ldd
11fc8b1d6d70fbacbb18181618fc3964=c&c_field.mix
b94a4486508afdc014c1ff3ea4f3d455=c&c_field.ldd
+b3b5a7faa502f747d3bc8ff5c63a99cb=M00_Tutorial.mix
+5da07b82073c698031b3bacdf286709c=M02.mix
+ceb5f647bec120fedffc9d9fc70f9ae6=M04.mix
+77e35ed03742c2a3916cae9baf6b119a=M07.mix
+72d92296beb9b14c1cd227e8ee592e19=M08.mix
+b3a1e43b578cd1f1899d920d9502b4e3=always.dat
+bbcd3fe6b90f81db7a55a1a214a75368=always.dbs
+f89d34c3bc56931a98aab08ad58d8ef1=c&c_city_flying.lsd
+7ddf27c53b4ff6e2a359f7e1b0fb9d2c=c&c_glacier_flying.ddb
+840a735015e5a5f97f9b595d27d6939e=c&c_glacier_flying.ldd
+9d5a1a6534e87623734592583ebd7514=c&c_glacier_flying.lsd
+908f10aa21b880481f00df979ee9ffc3=c&c_walls_flying.lsd
+e8a85eab76883e81ddf00c8a3832e62b=m09.dep
+d42dde72d9b33d70e27186d8576f7f28=m09.ldd
+3f313b1d45c289b4315b849613e24d5d=m09.lsd
+8a73e57ed8328458fc5b8e188431b58a=c&c_canyon.ldd
+3c2948416ae9ef87576244334dd96dcc=c&c_canyon.lsd
+fa8ec7d845fc98fa4e251c47ddda08ab=C&C_Canyon.mix
+b707c64d4ecbd8852a9203194ea870d6=c&c_city.ldd
+06cea509a508dbbe2a77a20837d8af1a=c&c_city.lsd
+66653f776fc48d86fab9bd4e7a79fa50=C&C_City.mix
+8980464e3794ee7814fa8e628a6bf03f=c&c_city_flying.ldd
+1d9c1184dcf889db9e89fa0f4cbbc2f3=c&c_city_flying.lsd
+3ae55a803f618419613d4f9449621311=C&C_City_Flying.mix
+e579475a79eb6064e850540dcdbc93db=c&c_complex.ldd
+1f65b69504fc5900583038f4878395b5=c&c_complex.lsd
+4874ba832f9244cec2fdb06298d84f28=C&C_Complex.mix
+1f384b687a76243972d041416e971dd7=c&c_field.ldd
+09c11621c186be319abc9c67bfb6c851=c&c_field.lsd
+48bff89bfedbe2dec0bed18d30419a5f=C&C_Field.mix
+3a15d5bee28c4d1efb49a80da9912971=c&c_glacier_flying.ddb
+ce8e22aafb5d126384ecde5d424c774c=c&c_glacier_flying.ldd
+10a0a9086ccb7885c6140f98f099084a=c&c_glacier_flying.lsd
+5fb74b0a88a3d17296ceb7eb01b48ecf=C&C_Glacier_Flying.mix
+2c827469432c744858076605522f3179=c&c_hourglass.ldd
+d165cb79cb5928e4235d325296affebd=c&c_hourglass.lsd
+df78d1b07d1a9e6982a2b059687a35be=C&C_Hourglass.mix
+22bb4baf876ba7dbd3500e7f7a6b06b4=c&c_islands.ldd
+0250e5ff5fc14d206b6047c8ce878fe9=c&c_islands.lsd
+4189d8309dd8af379cd6059c4161001b=C&C_Islands.mix
+d274bd131570e2c86ca9c1283740c316=c&c_mesa.ldd
+ae9f30a84b0addad158b9607d650d1a6=c&c_mesa.lsd
+1093a6bfa25597ae0b092e2ff0841e55=C&C_Mesa.mix
+b4b62db6b2b678e6280788c31be801a4=c&c_under.ldd
+d52da922114ee3815e3af8e14f8f3407=c&c_under.lsd
+5ff1b5861853e4dda9193f0de21c72ca=C&C_Under.mix
+681e7516692cb3b2573591f74b5a9d18=c&c_volcano.ldd
+b3fa999e7d40b378d57d7dacfba87f36=c&c_volcano.lsd
+0eb0f530b48926241cbea44a24ef6a6e=C&C_Volcano.mix
+c6e8f0e037a922caa4aeeed7d9e51400=C&C_Walls.ldd
+a44fe08c4400d45dfc7c26e545cc1c44=C&C_Walls.lsd
+3e9c2babf700a495f8403303ef6e1707=C&C_Walls.mix
+49cadbf6942f619922e2d9ef03b58e0e=C&C_Walls_Flying.ldd
+779dbe4cc96b4b75be0189699eeab597=C&C_Walls_Flying.lsd
+cedd5f9edf76b92a5f8af4099c1e2e0e=C&C_Walls_Flying.mix
+dbcbf16ad119e54b3f11d6fa44de2fcc=m09.dep
+504fa186ffab468a37a64fbd3ab26b37=m09.ldd
+9a1b58b2327389f8065f704dd6e4d8a0=m09.lsd
+9be4d74ee0deff8204e7091df81eeff4=M09.mix
+3cedfb2b7c127d456c37ff10c7cc65a8=always3.dat
diff -urN sourceold/scripts/dllmain.cpp source/scripts/dllmain.cpp
--- sourceold/scripts/dllmain.cpp 2019-06-22 07:43:44.225400000 +1000
+++ source/scripts/dllmain.cpp 2020-09-26 08:59:57.387156900 +1000
@@ -334,6 +334,9 @@
Retrieve_Waypaths = (rwpa)Address(tt,"Retrieve_Waypaths");
Retrieve_Waypoints = (rwpo)Address(tt,"Retrieve_Waypoints");
Get_Waypoint_Position = (gwp)Address(tt,"Get_Waypoint_Position");
+ Test_Raycast_Collision = (trc)Address(tt,"Test_Raycast_Collision");
+ Is_Inside_AABox = (iib)Address(tt,"Is_Inside_AABox");
+ Can_Generic_Soldier_Teleport = (cgst)Address(tt,"Can_Generic_Soldier_Teleport");
Create_Lightning = (cl)Address(tt,"Create_Lightning");
Set_Global_Stealth_Disable = (smie)Address(tt,"Set_Global_Stealth_Disable");
Get_Clouds = (gc) Address(tt, "Get_Clouds");
@@ -378,6 +381,39 @@
Cancel_Get_Pathfind_Distance = (cgpd)Address(tt,"Cancel_Get_Pathfind_Distance");
Get_Pathfind_Distance_Async = (gpda)Address(tt, "Get_Pathfind_Distance_Async");
Get_Pathfind_Distance_Blocking = (gpdb)Address(tt, "Get_Pathfind_Distance_Blocking");
+ Get_Multiplayer_Spawn_Location = (gmsl)Address(tt, "Get_Multiplayer_Spawn_Location");
+ Enable_Spawners_By_Name = (esbn)Address(tt, "Enable_Spawners_By_Name");
+ Is_Pathfind_Generated = (ipg)Address(tt, "Is_Pathfind_Generated");
+ Get_Closest_Pathfind_Spot = (gcps)Address(tt, "Get_Closest_Pathfind_Spot");
+ Get_Closest_Pathfind_Spot_Size = (gcpss)Address(tt, "Get_Closest_Pathfind_Spot_Size");
+ Get_Radio_Command_String = (grcs)Address(tt, "Get_Radio_Command_String");
+ Set_Emot_Icon = (sei)Address(tt, "Set_Emot_Icon");
+ Kill_Messages_Disabled = (kmd)Address(tt, "Kill_Messages_Disabled");
+ Is_Sidebar_Enabled = (ise)Address(tt, "Is_Sidebar_Enabled");
+ Is_Extras_Enabled = (iee)Address(tt, "Is_Extras_Enabled");
+ Can_Build_Ground = (cbg)Address(tt, "Can_Build_Ground");
+ Can_Build_Air = (cba)Address(tt, "Can_Build_Air");
+ Can_Build_Naval = (cbn)Address(tt, "Can_Build_Naval");
+ Is_Soldier_Busy = (isb)Address(tt, "Is_Soldier_Busy");
+ Is_On_Enemy_Pedestal = (ioep)Address(tt, "Is_On_Enemy_Pedestal");
+ Find_Closest_Poly_Position = (fcpp)Address(tt, "Find_Closest_Poly_Position");
+ Say_Dynamic_Dialogue = (sdd)Address(tt, "Say_Dynamic_Dialogue");
+ Say_Dynamic_Dialogue_Player = (sddp)Address(tt, "Say_Dynamic_Dialogue_Player");
+ Say_Dynamic_Dialogue_Team = (sddt)Address(tt, "Say_Dynamic_Dialogue_Team");
+ Enable_Letterbox_Player = (elp)Address(tt, "Enable_Letterbox_Player");
+ Create_Sound_Team = (cst)Address(tt, "Create_Sound_Team");
+ Create_2D_Sound_Team = (c2dst)Address(tt, "Create_2D_Sound_Team");
+ Create_2D_WAV_Sound_Team = (c2dwst)Address(tt, "Create_2D_WAV_Sound_Team");
+ Create_2D_WAV_Sound_Team_Dialog = (c2dwstd)Address(tt, "Create_2D_WAV_Sound_Team_Dialog");
+ Create_2D_WAV_Sound_Team_Cinematic = (c2dwstc)Address(tt, "Create_2D_WAV_Sound_Team_Cinematic");
+ Create_3D_WAV_Sound_At_Bone_Team = (c3dwsbt)Address(tt, "Create_3D_WAV_Sound_At_Bone_Team");
+ Create_3D_Sound_At_Bone_Team = (c3dsbt)Address(tt, "Create_3D_Sound_At_Bone_Team");
+ Stop_Sound_Player = (_Stop_Sound_Player)Address(tt, "Stop_Sound_Player");
+ Stop_Sound_Team = (_Stop_Sound_Team)Address(tt, "Stop_Sound_Team");
+ Set_Subobject_Animation = (ssa)Address(tt,"Set_Subobject_Animation");
+ Set_Time_Scale = (sts)Address(tt,"Set_Time_Scale");
+ Set_Subobject_Animation_Player = (ssap)Address(tt,"Set_Subobject_Animation_Player");
+ Write_File_Async = (wfa)Address(tt, "Write_File_Async");
#ifdef SSGM
SSGMGameManager::Init();
diff -urN sourceold/scripts/dp88_ar.cpp source/scripts/dp88_ar.cpp
--- sourceold/scripts/dp88_ar.cpp 2018-11-17 10:23:57.137600000 +1000
+++ source/scripts/dp88_ar.cpp 2020-09-10 09:08:27.950898100 +1000
@@ -14,6 +14,7 @@
#include "scripts.h"
#include "engine.h"
#include "dp88_ar.h"
+#include "ms.h"
#include "Definition.h"
#include "PurchaseSettingsDefClass.h"
#include "SoldierGameObj.h"
@@ -1031,6 +1032,7 @@
// Grant money to team and reset ore load level
Commands->Give_Money ( obj, (float)m_oreValue, true );
+ MS_AccessHelper::Give_Bot_Credits(Get_Object_Type(obj), (float)m_oreValue);
m_oreMined = 0;
m_oreValue = 0;
@@ -1453,7 +1455,7 @@
// OK, got a candidate zone, can we chronoshift here?
Vector3 zonePos = Commands->Get_Position(zone);
- if ( Commands->Get_Distance(zonePos,refineryPos) > maxDist || !CanChronoshiftToLocation(obj, zonePos) )
+ if (Vector3::Distance_Squared(zonePos, refineryPos) > maxDist * maxDist || !CanChronoshiftToLocation(obj, zonePos) )
continue;
// Is this zone in use for another chronoshift operation? If so then we cannot use it
@@ -3276,7 +3278,7 @@
{
// If we recieve a stop charging message from the tower we are currently
// charging then we should stop all actions
- if ( type == CUSTOM_PRISMTOWER_STOP_CHARGING && isAssistingTower && Commands->Get_ID(sender) == targetID )
+ if ( type == CUSTOM_PRISMTOWER_STOP_CHARGING && isAssistingTower && sender == m_target )
StopAssisting(obj);
@@ -3286,12 +3288,12 @@
else if ( type == CUSTOM_PRISMTOWER_REQUEST_CHARGING )
{
// Are we idle? If so then there's no reason not to simply start charging immediatly
- if ( targetID == 0 )
+ if ( !m_target )
StartAssisting(obj, sender, (float)param);
// Is this request from the tower we are currently charging? If so then update the last seen
// time and priority and forward the assistance request to any other adjacent towers
- else if ( isAssistingTower && targetID == Commands->Get_ID(sender) )
+ else if ( isAssistingTower && m_target == sender )
{
targetLastSeen = (int)time(NULL);
targetPriority = (float)param;
@@ -3319,7 +3321,7 @@
* Can this screw up the timings between charging towers and the attacking tower? Need to think
* this through sometime and possibly do some experimentation...
*/
- if ( targetID )
+ if ( m_target )
SendAssistanceRequests(obj);
/* Refill a single unit of charge if depleted */
@@ -3327,7 +3329,7 @@
Set_Current_Clip_Bullets(obj,1);
/* If current bullets > 1 and no enemy seen recently then additional charge is lost */
- if ( Get_Current_Bullets(obj) > 1 && targetID == 0 )
+ if ( Get_Current_Bullets(obj) > 1 && !m_target )
Set_Current_Bullets(obj,1);
}
@@ -3342,7 +3344,7 @@
{
// If the target is the tower we are currently charging then return
// the priority of that charging sequence
- if ( Commands->Get_ID(target) == targetID && isAssistingTower )
+ if ( m_target == target && isAssistingTower )
return targetPriority;
// Otherwise run the normal priority calculation
@@ -3354,7 +3356,7 @@
bool dp88_AR_Prism_Tower::checkTeam( GameObject *obj, GameObject *target )
{
// Return true for the tower we are charging, even though it is on the same team as us
- if ( Commands->Get_ID(target) == targetID && isAssistingTower )
+ if ( m_target == target && isAssistingTower )
return true;
// Otherwise run the normal check team function
@@ -3408,7 +3410,7 @@
void dp88_AR_Prism_Tower::StartAssisting(GameObject* obj, GameObject* tower, float priority)
{
// Set our new target ID and priority
- targetID = Commands->Get_ID(tower);
+ m_target = tower;
targetPriority = priority;
targetLastSeen = (int)time(NULL);
isAssistingTower = true;
@@ -3427,7 +3429,7 @@
{
if ( isAssistingTower )
{
- targetID = NULL;
+ m_target = nullptr;
targetPriority = 0;
isAssistingTower = false;
Commands->Action_Reset(obj, 101.0f);
@@ -3454,7 +3456,7 @@
// Send out assistance requests to all adjacent towers except the one we are charging, if any
for ( int i = 0; i < adjacentTowerCount; ++i )
{
- if ( adjacentTowers[i] != targetID && Commands->Find_Object(adjacentTowers[i]) != obj)
+ if ( adjacentTowers[i] != m_target->Get_ID() && Commands->Find_Object(adjacentTowers[i]) != obj)
Commands->Send_Custom_Event(obj, Commands->Find_Object(adjacentTowers[i]), CUSTOM_PRISMTOWER_REQUEST_CHARGING, (int)targetPriority, 0.0f );
}
}
diff -urN sourceold/scripts/dp88_buildingScripts.cpp source/scripts/dp88_buildingScripts.cpp
--- sourceold/scripts/dp88_buildingScripts.cpp 2018-11-17 10:23:57.142600000 +1000
+++ source/scripts/dp88_buildingScripts.cpp 2020-03-28 21:10:59.018844900 +1000
@@ -15,6 +15,7 @@
#include "engine.h"
#include "dp88_custom_timer_defines.h"
#include "dp88_buildingScripts.h"
+#include "ms.h"
#include "definition.h"
#include "BaseControllerClass.h"
#include "WarFactoryGameObj.h"
@@ -1078,6 +1079,8 @@
int team = Get_Object_Type(obj);
if ( team == 0 || team == 1 )
{
+ MS_AccessHelper::Give_Bot_Credits(team, Get_Float_Parameter("creditsPerSec"));
+
// NB: Calling Give_Money with the building controller as a parameter doesn't seem
// to give anyone any money, so get the first player on the team and use them as
// the target for Give_Money (true as third param to give to whole team)
@@ -1102,6 +1105,8 @@
{
if (team == 0 || team == 1)
{
+ MS_AccessHelper::Give_Bot_Credits(team, m_credits);
+
GameObject* pFirstPlayer = Find_First_Player(team);
if(pFirstPlayer)
{
diff -urN sourceold/scripts/dp88_customAI.cpp source/scripts/dp88_customAI.cpp
--- sourceold/scripts/dp88_customAI.cpp 2019-06-22 07:31:28.796400000 +1000
+++ source/scripts/dp88_customAI.cpp 2020-09-10 09:08:27.951896300 +1000
@@ -34,7 +34,7 @@
void dp88_customAI::Timer_Expired(GameObject *obj, int number)
{
if (TIMER_AI_THINK == number)
- Commands->Start_Timer(obj, this, 0.10f, TIMER_AI_THINK);
+ Commands->Start_Timer(obj, this, thinkTime, TIMER_AI_THINK);
}
// -------------------------------------------------------------------------------------------------
@@ -45,7 +45,8 @@
{
m_bAiEnabled = false;
AIStateChanged(pObj, false);
- targetID = 0;
+ m_target = nullptr;
+ hasTarget = false;
targetPriority = 0.0f;
targetLastSeen = 0;
}
@@ -53,11 +54,17 @@
else if ( message == CUSTOM_AI_ENABLEAI && !m_bAiEnabled )
{
m_bAiEnabled = true;
- targetID = 0;
+ m_target = nullptr;
+ hasTarget = false;
targetPriority = 0.0f;
targetLastSeen = 0;
AIStateChanged(pObj, true);
}
+
+ else if (message == CUSTOM_AI_RESET_ACTIONS)
+ {
+ ResetAllActions(pObj);
+ }
}
// -------------------------------------------------------------------------------------------------
@@ -85,7 +92,8 @@
{
if ( action_id == 2 )
{
- targetID = 0;
+ m_target = nullptr;
+ hasTarget = false;
targetPriority = 0.0f;
Commands->Action_Reset( obj, 100 );
}
@@ -104,19 +112,21 @@
// Set default values
m_bAiEnabled = true;
- targetID = 0;
+ m_target = nullptr;
+ hasTarget = false;
targetLastSeen = 0;
targetPriority = 0.0f;
m_bTargetPrimaryFire = true;
+ thinkTime = 1.0f;
// Set state
Commands->Enable_Hibernation(obj, false);
Commands->Innate_Enable(obj);
Commands->Enable_Enemy_Seen(obj, true);
- // Commands->Enable_Vehicle_Transitions(obj, false);
+ Commands->Enable_Vehicle_Transitions(obj, false);
// Start timer which runs for the lifetime of this object
- Commands->Start_Timer ( obj, this, 0.10f, TIMER_AI_THINK );
+ Commands->Start_Timer ( obj, this, 1.0, TIMER_AI_THINK );
}
// -------------------------------------------------------------------------------------------------
@@ -176,17 +186,19 @@
float dp88_customAI::getBasePriority(GameObject *target)
{
- if ( Get_Vehicle_Mode(target) == VEHICLE_TYPE_FLYING || (target->As_SoldierGameObj() && (Get_Fly_Mode(target)||Find_Script_On_Object(target,"dp88_AR_Paradrop")) ) )
- return priority_VTOL;
- if ( target->As_SoldierGameObj() )
- return priority_infantry;
- if ( target->As_VehicleGameObj() && Is_Script_Attached ( target, "dp88_AI_heavyVehicleMarker" ) )
- return priority_heavyVehicle;
- if ( target->As_VehicleGameObj() )
- return priority_lightVehicle;
- if ( target->As_BuildingGameObj() )
- return priority_building;
-
+ switch (GetTargetType(target))
+ {
+ case SOLDIER:
+ return priority_infantry;
+ case LIGHT_VEHICLE:
+ return priority_lightVehicle;
+ case HEAVY_VEHICLE:
+ return priority_heavyVehicle;
+ case FLYING:
+ return priority_VTOL;
+ case BUILDING:
+ return priority_building;
+ }
return 0;
}
@@ -200,9 +212,8 @@
if ( debug ) fprintf ( debugFile, "Calculating priority of %d (%s)\n", Commands->Get_ID(target), Commands->Get_Preset_Name(target) );
// Priority is 0 if the unit is dead or not on teams 0 or 1
- if ( ( Commands->Get_Health ( target ) + Commands->Get_Shield_Strength ( target ) ) == 0
- || ( Commands->Get_Player_Type ( target ) == -2) )
- //|| ( Commands->Get_Player_Type ( target ) != 0 && Commands->Get_Player_Type ( target ) != 1 ) )
+ if ( ( Commands->Get_Health ( target ) + Commands->Get_Shield_Strength ( target ) ) == 0
+ || Commands->Get_Player_Type ( target ) == SCRIPT_PLAYERTYPE_NEUTRAL || Commands->Get_Player_Type ( target ) == SCRIPT_PLAYERTYPE_SPECTATOR )
{
if ( debug ) fprintf ( debugFile, "Target %d is dead or unteamed, ignoring\n", Commands->Get_ID(target));
return 0.0;
@@ -214,7 +225,7 @@
return 0.0;
}
- if ( !m_bCanDetectStealth && target->As_SmartGameObj() && target->As_SmartGameObj()->Is_Stealthed() )
+ if ( !m_bCanDetectStealth && target->As_SmartGameObj() && target->As_SmartGameObj()->Is_Stealthed() && getDistance(obj, target) > target->As_SmartGameObj()->Get_Stealth_Fade_Distance() )
{
if ( debug ) fprintf ( debugFile, "Target %d is currently stealthed and stealth detection is disabled\n", Commands->Get_ID(target));
return 0.0;
@@ -238,7 +249,7 @@
// cost to purchase - not applicable to buildings)
if ( !target->As_BuildingGameObj() )
{
- int cost = Get_Team_Cost( Commands->Get_Preset_Name ( target ), Commands->Get_Player_Type ( target ) );
+ int cost = Get_Team_Cost( Commands->Get_Preset_ID ( target ), Commands->Get_Player_Type ( target ) );
priority += ((float)cost/10.0f) * modifier_target_value;
if ( debug ) fprintf ( debugFile, "\tTarget Value Modifier: Adding %.4f priority ((Value %d /10) * modifier %.2f)\n", ((float)cost/10.0f)*modifier_target_value, cost, modifier_target_value );
@@ -287,14 +298,19 @@
bool dp88_customAI::getPrimary ( GameObject *target )
{
- if ( target->As_SoldierGameObj() )
- return primary_infantry;
- else if ( Get_Vehicle_Mode ( target ) == VEHICLE_TYPE_FLYING )
- return primary_VTOL;
- else if ( target->As_VehicleGameObj() )
- return (Is_Script_Attached(target,"dp88_AI_heavyVehicleMarker")) ? primary_heavyVehicle : primary_lightVehicle;
- else if ( target->As_BuildingGameObj() )
- return primary_building;
+ switch (GetTargetType(target))
+ {
+ case SOLDIER:
+ return primary_infantry;
+ case LIGHT_VEHICLE:
+ return primary_lightVehicle;
+ case HEAVY_VEHICLE:
+ return primary_heavyVehicle;
+ case FLYING:
+ return primary_VTOL;
+ case BUILDING:
+ return primary_building;
+ }
return true;
}
@@ -318,17 +334,65 @@
return (vobj->Get_Action()->Is_Acting());
}
+// -------------------------------------------------------------------------------------------------
+
+dp88_customAI::TargetType dp88_customAI::GetTargetType(GameObject* target)
+{
+ if (target->As_BuildingGameObj() || Is_Script_Attached(target, "dp88_AI_Marker_Building"))
+ return BUILDING;
+ if (Is_Script_Attached(target, "JFW_Deployable_Aircraft_Deployed"))
+ return LIGHT_VEHICLE;
+ if ((Get_Vehicle_Mode(target) == VEHICLE_TYPE_FLYING) || (target->As_SoldierGameObj() && (Get_Fly_Mode(target) || Find_Script_On_Object(target, "MS_Paradrop") || Find_Script_On_Object(target, "dp88_AR_Paradrop"))))
+ return FLYING;
+ if (target->As_SoldierGameObj())
+ return SOLDIER;
+ if (target->As_VehicleGameObj() && (Is_Script_Attached(target, "dp88_AI_Marker_HeavyVehicle") || Is_Script_Attached ( target, "dp88_AI_heavyVehicleMarker")))
+ return HEAVY_VEHICLE;
+ if (Is_Script_Attached(target, "dp88_AI_Marker_Repairable"))
+ return REPAIRABLE;
+ if (target->As_VehicleGameObj())
+ return LIGHT_VEHICLE;
+
+ return UNKNOWN;
+}
+
+
+/*------------------------
+Deprecated heavy vehicle marker script
+--------------------------*/
+void dp88_AI_heavyVehicleMarker::Created(GameObject* obj)
+{
+ Console_Output("[%d:%hs:%hs] This script is deprecated, use dp88_AI_Marker_HeavyVehicle instead\n", Commands->Get_ID(obj), Commands->Get_Preset_Name(obj), this->Get_Name());
+ Attach_Script_V(obj,"dp88_AI_Marker_HeavyVehicle","0");
+ Destroy_Script();
+}
+/*------------------------
+Repairable marker script
+--------------------------*/
+void dp88_AI_Marker_Repairable::Created(GameObject* obj)
+{
+ pathfindDistance = Get_Float_Parameter("Pathfind_Distance");
+}
+// -------------------------------------------------------------------------------------------------
+float dp88_AI_Marker_Repairable::Get_Distance_From_Pathfind()
+{
+ return pathfindDistance;
+}
/*------------------------
Unit AI base class
--------------------------*/
+DynamicVectorClass dp88_AI_Unit::ListOfAIUnits;
+
+// -------------------------------------------------------------------------------------------------
+
void dp88_AI_Unit::Created(GameObject* obj)
{
// Base class should not be instantiated
@@ -345,6 +409,23 @@
m_bMovingToTarget = false;
m_bMovingToObjective = false;
m_pCurrentObjective = NULL;
+ ListOfAIUnits.Add(this);
+}
+
+// -------------------------------------------------------------------------------------------------
+
+void dp88_AI_Unit::Detach(GameObject* obj)
+{
+ ListOfAIUnits.DeleteObj(this);
+ dp88_customAI::Detach(obj);
+}
+
+// -------------------------------------------------------------------------------------------------
+
+void dp88_AI_Unit::Force_Clear_Current_Objective()
+{
+ m_pCurrentObjective = nullptr;
+ m_bMovingToObjective = false;
}
// -------------------------------------------------------------------------------------------------
@@ -354,16 +435,14 @@
// Check target is still alive, still an enemy (eg: stolen vehicles) and in range
if (TIMER_AI_THINK == number)
{
- GameObject* target = (NULL != targetID) ? Commands->Find_Object(targetID) : NULL;
-
// Check the current objective, if any, is still valid
if (NULL != m_pCurrentObjective && !dp88_AI_Objective::IsValidObjective(m_pCurrentObjective))
{
m_pCurrentObjective = NULL;
if (m_bMovingToObjective)
{
- if (NULL != target && IsValidTarget(obj, target))
- AttackTarget(obj, target);
+ if (m_target && IsValidTarget(obj, m_target))
+ AttackTarget(obj, m_target);
else
ResetAllActions(obj);
}
@@ -373,23 +452,24 @@
if (NULL == m_pCurrentObjective)
{
m_pCurrentObjective = ChooseNewObjective(obj);
- if (NULL != m_pCurrentObjective && (NULL == target || !ShouldPursueTarget(obj, target)))
+ if (NULL != m_pCurrentObjective && (!m_target || !ShouldPursueTarget(obj, m_target)))
GoToObjective(obj);
}
// If we have a target check it is still valid
- if (NULL != targetID)
+ if (m_target)
{
- if (NULL == target || !IsValidTarget(obj, target) || (int)time(NULL) - targetLastSeen > 3)
+ if (!IsValidTarget(obj, m_target) || (int)time(NULL) - targetLastSeen > 3)
{
- targetID = NULL;
+ m_target = nullptr;
+ hasTarget = false;
ResetAllActions(obj);
}
// Check if we need to move closer to our target
- else if (!m_bMovingToTarget && ShouldPursueTarget(obj, target) && getDistance(obj, target) > GetPreferredAttackRange(obj, target))
+ else if (!m_bMovingToTarget && ShouldPursueTarget(obj, m_target) && getDistance(obj, m_target) > GetPreferredAttackRange(obj, m_target))
{
- AttackTarget(obj, target); // Will modify the action with movement parameters
+ AttackTarget(obj, m_target); // Will modify the action with movement parameters
}
}
@@ -409,7 +489,10 @@
ResetAllActions(obj);
if (MOVEMENT_COMPLETE_ARRIVED == reason && action_id == ACTION_ID_ATTACK_TARGET)
- AttackTarget(obj, Commands->Find_Object(targetID));
+ {
+ if (m_target)
+ AttackTarget(obj, m_target);
+ }
}
// -------------------------------------------------------------------------------------------------
@@ -431,7 +514,7 @@
// -------------------------------------------------------------------------------------------------
-void dp88_AI_Unit::GoToObjective(GameObject *obj)
+void dp88_AI_Unit::GoToObjective(GameObject *obj, float speed)
{
if (NULL == m_pCurrentObjective)
return;
@@ -439,7 +522,7 @@
ActionParamsStruct params;
bool bModifyAction = false;
- if (NULL == targetID || !obj->As_SmartGameObj()->Get_Action()->Is_Acting())
+ if (!m_target || !obj->As_SmartGameObj()->Get_Action()->Is_Acting())
{
ResetAllActions(obj);
params.Set_Basic(this, 80, ACTION_ID_MOVE_TO_OBJECTIVE);
@@ -453,9 +536,10 @@
// Setup the movement parameters
int arrivalRange = m_pCurrentObjective->GetRange();
- m_bMovingToObjective = arrivalRange < getDistance(obj, m_pCurrentObjective->GetGameObject());
+ // Fix arrival range by letting it 1 meter further than wanted, because soldiers keep calling action_complete when 1.58m away than 1.0 wanted.
+ m_bMovingToObjective = (arrivalRange + 1) < getDistance(obj, m_pCurrentObjective->GetGameObject());
if (m_bMovingToObjective)
- params.Set_Movement(m_pCurrentObjective->GetGameObject(), 1.0f, (float)arrivalRange);
+ params.Set_Movement(m_pCurrentObjective->GetGameObject(), speed, (float)arrivalRange);
else
{
// Already in range of the objective
@@ -463,6 +547,9 @@
return;
}
+ if (GetTargetType(obj) == FLYING)
+ params.MovePathfind = false;
+
// Commence the action
if (bModifyAction)
Commands->Modify_Action(obj, params.ActionID, params, true, false);
@@ -491,13 +578,14 @@
}
// Setup parameters to track state
- targetID = Commands->Get_ID(target);
+ m_target = target;
+ hasTarget = true;
m_bTargetPrimaryFire = getPrimary(target);
targetPriority = getPriority(obj, target);
targetLastSeen = (int)time(NULL);
// Setup the attack parameters
- params.Set_Attack(target, (float)((m_bTargetPrimaryFire)?primary_maxRange:secondary_maxRange), 0.0, true);
+ params.Set_Attack(target, (float)((m_bTargetPrimaryFire)?primary_maxRange:secondary_maxRange), 0.0, m_bTargetPrimaryFire);
params.AttackCheckBlocked = false;
// Setup the movement parameters if we want to persue the target
@@ -569,16 +657,20 @@
//fprintf( debugFile, "Seen enemy %s\n", Commands->Get_Preset_Name(enemy) );
// If this is our current target update it's last seen time and priority
- if (Commands->Get_ID(enemy) == targetID)
+ if (enemy == m_target)
{
targetLastSeen = (int)time(NULL);
- targetPriority = getPriority(obj, targetID);
+ targetPriority = getPriority(obj, m_target);
return;
}
+ // Update current target priority (needed due to linked hp objects)
+ if (m_target)
+ targetPriority = getPriority(obj, m_target);
+
// Get priority for seen object and return if 0 or lower than current target
float seenPriority = getPriority( obj, enemy );
- if (seenPriority == 0.0 || (targetID!=0 && seenPriority <= targetPriority))
+ if (seenPriority == 0.0 || (m_target && seenPriority <= targetPriority))
return;
//fprintf( debugFile, "Higher priority than existing target... attacking!\n" );
@@ -588,6 +680,9 @@
return;
// All good, attack the enemy
+ m_target = enemy;
+ hasTarget = true;
+ targetLastSeen = (int)time(NULL);
AttackTarget(obj, enemy);
}
@@ -608,8 +703,8 @@
int maxRange = attackPrimary ? primary_maxRange : secondary_maxRange;
return 0.0f < Commands->Get_Health(target)
- && 2 != Commands->Get_Player_Type(target)
- && Commands->Get_Player_Type(target) != Commands->Get_Player_Type(obj)
+ && SCRIPT_PLAYERTYPE_NEUTRAL != Get_Object_Type(target)
+ && (Get_Object_Type(target) != Get_Object_Type(obj) || GetTargetType(target) == REPAIRABLE)
&& targetDistance >= minRange
&& (ShouldPursueTarget(obj, target) || targetDistance <= maxRange);
}
@@ -618,9 +713,10 @@
dp88_AI_Objective* dp88_AI_Tank_Offensive::ChooseNewObjective(GameObject* obj)
{
- dp88_AI_Objective* pObjective = dp88_AI_Objective::GetBestObjective(obj, dp88_AI_Objective::TYPE_OFFENSIVE, modifier_distance);
+ DynamicVectorClass ignoredObjectives;
+ dp88_AI_Objective* pObjective = dp88_AI_Objective::GetBestObjective(obj, dp88_AI_Objective::TYPE_OFFENSIVE, modifier_distance, ignoredObjectives);
if (NULL == pObjective)
- pObjective = dp88_AI_Objective::GetBestObjective(obj, dp88_AI_Objective::TYPE_DEFENSIVE, modifier_distance);
+ pObjective = dp88_AI_Objective::GetBestObjective(obj, dp88_AI_Objective::TYPE_DEFENSIVE, modifier_distance, ignoredObjectives);
return pObjective;
}
@@ -688,7 +784,7 @@
if ( debug ) fprintf( debugFile, "Seen an enemy: %d (%s)\n", Commands->Get_ID(enemy), Commands->Get_Preset_Name(enemy) );
// If this is our current target update last seen time and priority
- if ( Commands->Get_ID ( enemy ) == targetID )
+ if ( enemy == m_target )
{
if ( debug ) fprintf( debugFile, "Enemy is current target, last seen time and priority updated\n" );
targetLastSeen = (int)time(NULL);
@@ -724,12 +820,13 @@
// If this is a higher priority than our current target attack it
- if ( targetID == 0 || enemyPriority > targetPriority )
+ if ( !m_target || enemyPriority > targetPriority )
{
- if ( debug && targetID == 0 ) fprintf ( debugFile, "No current target to compare with, attacking enemy!\n" );
+ if ( debug && !m_target ) fprintf ( debugFile, "No current target to compare with, attacking enemy!\n" );
else if ( debug ) fprintf ( debugFile, "New enemy has a higher priority than current target, attacking enemy\n" );
- targetID = Commands->Get_ID ( enemy );
+ m_target = enemy;
+ hasTarget = true;
targetLastSeen = (int)time(NULL);
targetPriority = enemyPriority;
m_bTargetPrimaryFire = attackPrimary;
@@ -768,18 +865,18 @@
// Check target is still alive, still an enemy (eg: stolen vehicles) and in range
if ( number == TIMER_AI_THINK )
{
- if ( targetID != 0 )
+ if ( hasTarget )
{
- GameObject *target = Commands->Find_Object ( targetID );
- if (!target || !checkPowerState(obj)
- || ( Commands->Get_Health ( target ) + Commands->Get_Shield_Strength ( target ) <= 0 )
- || !checkTeam ( obj, target )
- || !checkRange ( obj, target, m_bTargetPrimaryFire )
+ if (!m_target || !checkPowerState(obj)
+ || ( Commands->Get_Health ( m_target ) + Commands->Get_Shield_Strength ( m_target ) <= 0 )
+ || !checkTeam ( obj, m_target )
+ || !checkRange ( obj, m_target, m_bTargetPrimaryFire )
|| (int)time(NULL) - targetLastSeen > 3
- || ( target->As_VehicleGameObj() && !IsVehicleAIEnabled(target->As_VehicleGameObj()) && IsVehicleEmpty(target->As_VehicleGameObj()) ))
+ || ( m_target->As_VehicleGameObj() && !IsVehicleAIEnabled(m_target->As_VehicleGameObj()) && IsVehicleEmpty(m_target->As_VehicleGameObj()) ))
{
- if ( debug ) fprintf ( debugFile, "Target %d no longer valid, ceasing attack.\n", targetID);
- targetID = 0;
+ if ( debug ) fprintf ( debugFile, "Target %d no longer valid, ceasing attack.\n", m_target->Get_ID());
+ m_target = nullptr;
+ hasTarget = false;
targetPriority = 0.0f;
targetLastSeen = 0;
stopAttacking(obj);
@@ -787,15 +884,15 @@
// Otherwise we are OK to continue attacking... if this is an infantry unit
// and splash targetting is enabled then update targetting position
- else if ( splashInfantry && target->As_SoldierGameObj())
+ else if ( splashInfantry && m_target->As_SoldierGameObj())
{
- if(obj->As_SmartGameObj()->Is_Splash_Possible(target->As_PhysicalGameObj()))
+ if(obj->As_SmartGameObj()->Is_Splash_Possible(m_target->As_PhysicalGameObj()))
{
- attackLocation ( obj, Commands->Get_Position(target), m_bTargetPrimaryFire );
+ attackLocation ( obj, Commands->Get_Position(m_target), m_bTargetPrimaryFire );
}
else
{
- attackLocation ( obj, target->As_SoldierGameObj()->Get_Bullseye_Position(), m_bTargetPrimaryFire );
+ attackLocation ( obj, m_target->As_SoldierGameObj()->Get_Bullseye_Position(), m_bTargetPrimaryFire );
}
}
}
@@ -969,11 +1066,11 @@
if ( number == TIMER_AI_THINK && m_deploymentState == STATE_DEPLOYED )
{
// If we have no target and have reached the undeploy timeout then trigger undeployment
- if ( targetID == 0 && time(NULL) > m_undeployTime )
+ if ( !m_target && time(NULL) > m_undeployTime )
Undeploy(pSelf);
// Else, if we have an active target, update the undeployment timeout time
- else if ( targetID != 0 )
+ else if ( m_target )
m_undeployTime = time(NULL)+Get_Int_Parameter("Deploy_Timeout");
}
@@ -1008,7 +1105,8 @@
// Reset targetting parameters, otherwise the next Enemy_Seen call will think we are already attacking
// an enemy and not trigger the appropriate actions we are depending upon
- targetID = 0;
+ m_target = nullptr;
+ hasTarget = false;
}
else if ( m_deploymentState == STATE_UNDEPLOYING )
m_deploymentState = STATE_UNDEPLOYED;
@@ -1185,7 +1283,7 @@
// todo: set bpreloading as appropriate
- if (NULL != targetID)
+ if (m_target)
StartCharging(pSelf);
else
ApplyIdleAnimation(pSelf);
@@ -1193,7 +1291,7 @@
// Has our target already died or ran like a coward before we could empty our clip? If so then
// reset and trigger a reload (so we don't have a partial charge next time round)
- else if (NULL == targetID)
+ else if (!m_target)
{
m_bIsDischarging = false;
Set_Current_Bullets(pSelf, 0);
@@ -1208,7 +1306,7 @@
if (number == TIMER_AI_CHARGE_PRERELOAD_COMPLETE && m_bIsPreReloading)
{
m_bIsPreReloading = false;
- if (NULL != targetID)
+ if (m_target)
StartCharging(pSelf);
}
@@ -1289,7 +1387,7 @@
{
// If we are not charging, not discharging, powered and have a target then we can start a new
// charging cycle
- if (!m_bIsPreReloading && !m_bIsCharging && !m_bIsDischarging && checkPowerState(pSelf) && targetID != NULL)
+ if (!m_bIsPreReloading && !m_bIsCharging && !m_bIsDischarging && checkPowerState(pSelf) && m_target)
{
m_bIsCharging = true;
@@ -1315,18 +1413,15 @@
m_bIsCharging = false;
// Got an enemy? Also double check power state whilst we are here, just to be sure
- if (targetID != NULL && checkPowerState(pSelf))
+ if (m_target && checkPowerState(pSelf))
{
- if (GameObject* pTarget = Commands->Find_Object(targetID))
- {
m_bIsDischarging = true;
// Call into the base class and let it do it's thing
- if (splashInfantry && pTarget->As_SoldierGameObj())
- dp88_AI_Turret::attackLocation(pSelf, Commands->Get_Position(pTarget), m_bTargetPrimaryFire);
+ if (splashInfantry && m_target->As_SoldierGameObj())
+ dp88_AI_Turret::attackLocation(pSelf, Commands->Get_Position(m_target), m_bTargetPrimaryFire);
else
- dp88_AI_Turret::attackTarget(pSelf, pTarget, m_bTargetPrimaryFire);
- }
+ dp88_AI_Turret::attackTarget(pSelf, m_target, m_bTargetPrimaryFire);
}
// If we didn't find anything to shoot at then apply the idle animation again
@@ -1429,13 +1524,17 @@
void dp88_AI_Objective::Created ( GameObject* obj )
{
// Register objective
- m_objID = Commands->Get_ID(obj);
+ //m_objID = Commands->Get_ID(obj);
Objectives.Add(this);
// Store data
- m_type = (unsigned char)Get_Int_Parameter("Type");
+ m_type = (unsigned int)Get_Int_Parameter("Type");
m_range = Get_Int_Parameter("Range");
m_team = Get_Int_Parameter("Team");
+ m_debugTag = Get_Parameter("Debug_Tag");
+ if (strlen(m_debugTag) == 0) {
+ m_debugTag = "No Tag";
+ }
m_priority[UNITTYPE_SOLDIER] = Get_Int_Parameter("Priority_Soldier");
m_priority[UNITTYPE_LVEHICLE] = Get_Int_Parameter("Priority_Light_Vehicle");
@@ -1451,13 +1550,24 @@
// De-register objective
if (Exe != EXE_LEVELEDIT)
Objectives.DeleteObj(this);
+
+ // delete references to this objective from AI units so they don't try to access our memory after it's freed
+ for (int i = 0; i < dp88_AI_Unit::ListOfAIUnits.Count(); i++)
+ {
+ dp88_AI_Unit *unit = dp88_AI_Unit::ListOfAIUnits[i];
+ if (unit->Get_Current_Objective() == this)
+ unit->Force_Clear_Current_Objective();
+ }
}
// -------------------------------------------------------------------------------------------------
GameObject* dp88_AI_Objective::GetGameObject()
{
- return Commands->Find_Object(m_objID);
+ // NOTE: We no longer need to store object IDs since the objective script itself is destroyed when its owner is destroyed anyways.
+ // The objective is removed from all AI units when destroyed (see Detach()), so we don't need to do lookups at all.
+ return Owner();
+ // return Commands->Find_Object(m_objID);
}
// -------------------------------------------------------------------------------------------------
@@ -1472,7 +1582,7 @@
if (obj->As_VehicleGameObj())
{
- if (Is_Script_Attached(obj, "dp88_AI_heavyVehicleMarker"))
+ if (Is_Script_Attached(obj, "dp88_AI_heavyVehicleMarker") || Is_Script_Attached(obj, "dp88_AI_Marker_HeavyVehicle"))
return UNITTYPE_HVEHICLE;
return UNITTYPE_LVEHICLE;
}
@@ -1500,22 +1610,25 @@
// -------------------------------------------------------------------------------------------------
-dp88_AI_Objective* dp88_AI_Objective::GetBestObjective(GameObject* obj, unsigned char objective_type, float distance_modifier)
+dp88_AI_Objective* dp88_AI_Objective::GetBestObjective(GameObject* obj, unsigned int objective_type, float distance_modifier, DynamicVectorClass ignoredObjectives)
{
dp88_AI_Objective* result = NULL;
float top_priority = 0.0f;
+ float best_distance = FLT_MAX;
int team = Get_Object_Type(obj);
for ( int i = 0; i < Objectives.Count(); ++i )
{
int objTeam = Objectives[i]->GetTeam();
- if (objective_type != Objectives[i]->GetType() || (objTeam != 2 && team != objTeam))
+ if (objective_type != Objectives[i]->GetType() || (objTeam != 2 && team != objTeam) || (ignoredObjectives.Length() && ignoredObjectives.ID(Objectives[i]->GetGameObject()->Get_ID()) != -1))
continue;
float priority = Objectives[i]->GetPriority(obj, distance_modifier);
- if( priority > top_priority )
+ float distance = Vector3::Distance_Squared(Commands->Get_Position(obj), Commands->Get_Position(Objectives[i]->GetGameObject()));
+ if( priority > top_priority || (priority > 0 && priority == top_priority && distance < best_distance) )
{
top_priority = priority;
+ best_distance = distance;
result = Objectives[i];
}
}
@@ -1525,6 +1638,40 @@
// -------------------------------------------------------------------------------------------------
+int dp88_AI_Objective::CountObjectives(int team, unsigned int objective_type)
+{
+ int count = 0;
+
+ for (int i = 0; i < Objectives.Count(); ++i)
+ {
+ int objTeam = Objectives[i]->GetTeam();
+ if (objective_type != Objectives[i]->GetType() || (objTeam != 2 && team != objTeam))
+ continue;
+ count++;
+ }
+
+ return count;
+}
+
+// -------------------------------------------------------------------------------------------------
+
+int dp88_AI_Objective::CountUnitObjectives(int team, unsigned int objective_type, GameObject* obj, float distance_modifier)
+{
+ int count = 0;
+
+ for (int i = 0; i < Objectives.Count(); ++i)
+ {
+ int objTeam = Objectives[i]->GetTeam();
+ if (objective_type != Objectives[i]->GetType() || (objTeam != 2 && team != objTeam) || Objectives[i]->GetPriority(obj, distance_modifier) == 0)
+ continue;
+ count++;
+ }
+
+ return count;
+}
+
+// -------------------------------------------------------------------------------------------------
+
bool dp88_AI_Objective::IsValidObjective(dp88_AI_Objective* pObjective)
{
for ( int i = 0; i < Objectives.Count(); ++i )
@@ -1546,7 +1693,8 @@
"Priority_Soldier=1:int,"
"Priority_Light_Vehicle=1:int,"
"Priority_Heavy_Vehicle=1:int,"
- "Priority_Aircraft=1:int");
+ "Priority_Aircraft=1:int,"
+ "Debug_Tag:string");
@@ -1557,9 +1705,18 @@
// Script Registrants
// -------------------------------------------------------------------------------------------------
-// Heavy vehicle marker (dummy script)
+// Heavy vehicle marker (dummy script, deprecated )
ScriptRegistrant dp88_AI_heavyVehicleMarker_Registrant("dp88_AI_heavyVehicleMarker","");
+// Building marker (dummy script)
+ScriptRegistrant dp88_AI_Marker_Building_Registrant("dp88_AI_Marker_Building","");
+
+// Heavy vehicle marker (dummy script)
+ScriptRegistrant dp88_AI_Marker_HeavyVehicle_Registrant("dp88_AI_Marker_HeavyVehicle","");
+
+// Repair target marker (dummy script)
+ScriptRegistrant dp88_AI_Marker_Repairable_Registrant("dp88_AI_Marker_Repairable","Pathfind_Distance=5.0:float");
+
ScriptRegistrant dp88_AI_Turret_Registrant("dp88_AI_Turret","Priority_Infantry=1.0:float,Weapon_Infantry=1:int,Splash_Infantry=0:int,Priority_Light_Vehicle=5.0:float,Weapon_Light_Vehicle=1:int,Priority_Heavy_Vehicle=7.0:float,Weapon_Heavy_Vehicle=1:int,Priority_VTOL=5.0:float,Weapon_VTOL=1:int,Min_Attack_Range=0:int,Max_Attack_Range=150:int,Min_Attack_Range_Secondary=0:int,Max_Attack_Range_Secondary=150:int,Modifier_Distance=0.25:float,Modifier_Target_Damage=0.1:float,Modifier_Target_Value=0.05:float,Requires_Power=0:int,Debug=0:int,Detects_Stealth=1:int");
ScriptRegistrant dp88_AI_PopupTurret_Registrant("dp88_AI_PopupTurret","Priority_Infantry=1.0:float,Weapon_Infantry=1:int,Splash_Infantry=0:int,Priority_Light_Vehicle=5.0:float,Weapon_Light_Vehicle=1:int,Priority_Heavy_Vehicle=7.0:float,Weapon_Heavy_Vehicle=1:int,Priority_VTOL=5.0:float,Weapon_VTOL=1:int,Min_Attack_Range=0:int,Max_Attack_Range=150:int,Min_Attack_Range_Secondary=0:int,Max_Attack_Range_Secondary=150:int,Deploy_Animation:string,Deploy_Animation_Frames:int,Deploy_Sound:string,Deploy_Timeout:int,Spotter_Preset:string,Modifier_Distance=0.25:float,Modifier_Target_Damage=0.1:float,Modifier_Target_Value=0.05:float,Requires_Power=0:int,Debug=0:int,Detects_Stealth=1:int");
ScriptRegistrant dp88_AI_PopupTurret_Spotter_Registrant("dp88_AI_PopupTurret_Spotter","tId:int");
diff -urN sourceold/scripts/dp88_customAI.h source/scripts/dp88_customAI.h
--- sourceold/scripts/dp88_customAI.h 2018-11-17 10:23:57.146600000 +1000
+++ source/scripts/dp88_customAI.h 2020-09-10 09:08:27.952893600 +1000
@@ -13,8 +13,24 @@
#include "LoopedAnimationController.h"
#include "ObserverImpClass.h"
+#include "ReferencerClass.h"
+
+class ActionParamsStruct;
+
+class Pathfind_Help_Implementer
+{
+public:
+ virtual ~Pathfind_Help_Implementer() {};
+ virtual bool Should_Ignore_Blocked_Checking(GameObject *obj) = 0;
+ virtual void Prepare_Getting_Around(GameObject *obj) = 0;
+ virtual void Stop_Getting_Around(GameObject *obj) = 0;
+ virtual void On_Unable_To_Get_Unstuck(GameObject *obj) = 0;
+ // Modify action params during getting unstuck to include target shooting, if any exist
+ virtual ActionParamsStruct Get_Param_Attack_Modifications(ActionParamsStruct params) = 0;
+};
// Forward declaration
+class VehicleGameObj;
class dp88_AI_Objective;
class dp88_AI_ChargedTurret_AnimationObserver;
@@ -72,11 +88,16 @@
int secondary_minRange, secondary_maxRange;
// Current target state
- int targetID;
+ //int targetID;
+ ReferencerClass m_target;
+ bool hasTarget;
int targetLastSeen;
float targetPriority;
bool m_bTargetPrimaryFire;
+ // Brain speed
+ float thinkTime;
+
// Other settings
bool m_bAiEnabled;
bool m_bCanDetectStealth;
@@ -85,6 +106,16 @@
bool debug;
FILE* debugFile;
+ // Target types
+ enum TargetType {
+ SOLDIER = 0,
+ LIGHT_VEHICLE,
+ HEAVY_VEHICLE,
+ FLYING,
+ BUILDING,
+ REPAIRABLE,
+ UNKNOWN
+ };
@@ -126,11 +157,40 @@
/* Utility functions for both priority calculations and AI scripts to utilise */
virtual bool IsVehicleEmpty( VehicleGameObj* vobj );
virtual bool IsVehicleAIEnabled( VehicleGameObj* vobj );
+
+ // "Global" decider about what a unit type is
+ static TargetType GetTargetType(GameObject* obj);
+};
+
+// -------------------------------------------------------------------------------------------------
+
+/*!
+* \brief danpaul88's Custom AI Heavy Vehicle Marker
+* \author Daniel Paul (danpaul88@yahoo.co.uk)
+*
+* This is a dummy script with no functionality which can be attached to an object to indicate all of
+* my custom AI scripts should treat this as a heavy vehicle. Any vehicle without this script will be
+* considered to be a light vehicle.
+*/
+class dp88_AI_heavyVehicleMarker : public ScriptImpClass
+{
+ void Created(GameObject* obj);
};
// -------------------------------------------------------------------------------------------------
/*!
+* \brief danpaul88's Custom AI Building Marker
+* \author Daniel Paul (danpaul88@yahoo.co.uk)
+*
+* This is a dummy script with no functionality which can be attached to an object to indicate all of
+* my custom AI scripts should treat this as a building.
+*/
+class dp88_AI_Marker_Building : public ScriptImpClass {};
+
+// -------------------------------------------------------------------------------------------------
+
+/*!
* \brief danpaul88's Custom AI Heavy Vehicle Marker
* \author Daniel Paul (danpaul88@yahoo.co.uk)
*
@@ -138,7 +198,25 @@
* my custom AI scripts should treat this as a heavy vehicle. Any vehicle without this script will be
* considered to be a light vehicle.
*/
-class dp88_AI_heavyVehicleMarker : public ScriptImpClass{};
+class dp88_AI_Marker_HeavyVehicle : public ScriptImpClass {};
+
+// -------------------------------------------------------------------------------------------------
+
+/*!
+* \brief danpaul88's Custom AI Repair Target Marker
+* \author Daniel Paul (danpaul88@yahoo.co.uk)
+*
+* This is a dummy script with no functionality which can be attached to an object to indicate all of
+* my custom AI scripts should treat this as a repair target.
+*/
+class dp88_AI_Marker_Repairable : public ScriptImpClass
+{
+public:
+ void Created(GameObject* obj);
+ float Get_Distance_From_Pathfind();
+protected:
+ float pathfindDistance;
+};
// -------------------------------------------------------------------------------------------------
@@ -154,6 +232,7 @@
public:
// Game Events
void Created(GameObject *obj);
+ void Detach(GameObject *obj);
void Timer_Expired(GameObject *obj, int number);
void Action_Complete(GameObject *obj, int action_id, ActionCompleteReason reason);
@@ -161,6 +240,12 @@
virtual void Init(GameObject *obj);
virtual void loadSettings(GameObject *obj, bool loadSecondaryFireSettings, bool loadBuildingTargetSettings);
+ virtual void Force_Clear_Current_Objective();
+ dp88_AI_Objective* Get_Current_Objective() { return m_pCurrentObjective; }
+
+ // used in combination with Force_Clear_Current_Objective() to invalidate references to objectives when they are deleted (prevents use-after-free bugs)
+ static DynamicVectorClass ListOfAIUnits;
+
protected:
static const int ACTION_ID_MOVE_TO_OBJECTIVE = 7850001;
static const int ACTION_ID_ATTACK_TARGET = 7850002;
@@ -169,7 +254,7 @@
void ResetAllActions(GameObject* obj);
// Go to the location of the current objective
- virtual void GoToObjective(GameObject *obj);
+ virtual void GoToObjective(GameObject *obj, float speed = 1.0f);
// Attack the specified target
virtual void AttackTarget(GameObject *obj, GameObject *target);
@@ -746,9 +831,10 @@
GameObject* GetGameObject();
- unsigned char GetType() { return m_type; }
+ unsigned int GetType() { return m_type; }
int GetTeam() { return m_team; }
int GetRange() { return m_range; }
+ const char* GetDebugTag() { return m_debugTag; }
/*! Get the priority of this objective for the specified AI unit */
float GetPriority(GameObject* obj, float distance_modifier);
@@ -757,16 +843,26 @@
* Finds the most suitable objective of a given type for the specified unit, based on the distance
* to the objective and their distance modifier
*/
- static dp88_AI_Objective* GetBestObjective ( GameObject* obj, unsigned char objective_type, float distance_modifier );
+ static dp88_AI_Objective* GetBestObjective ( GameObject* obj, unsigned int objective_type, float distance_modifier, DynamicVectorClass ignoredObjectives );
+
+ /*!
+ * Counts the existing objectives of a given type for the specified team
+ */
+ static int CountObjectives( int team, unsigned int objective_type );
+
+ /*!
+ * Counts the existing valid objectives of a given type for the specified unit
+ */
+ static int CountUnitObjectives( int team, unsigned int objective_type, GameObject* obj, float distance_modifier );
/*! Checks if the specified objective is still valid */
static bool IsValidObjective ( dp88_AI_Objective* pObjective );
/*! \name Objective types */
/*! @{ */
- const static unsigned char TYPE_OFFENSIVE = 1;
- const static unsigned char TYPE_DEFENSIVE = 2;
- const static unsigned char TYPE_ENGINEERING = 3;
+ const static unsigned int TYPE_OFFENSIVE = 1;
+ const static unsigned int TYPE_DEFENSIVE = 2;
+ const static unsigned int TYPE_ENGINEERING = 3;
/*! @} */
protected:
@@ -783,14 +879,15 @@
/*! Get the unit type of the specified unit */
unsigned char GetUnitType(GameObject* obj);
- int m_objID;;
+ //int m_objID;;
/*! \name Cached Script Parameters */
/*! @{ */
- unsigned char m_type;
+ unsigned int m_type;
int m_priority[UNITTYPE_MAX + 1];
int m_range;
int m_team;
+ const char* m_debugTag;
/*! @} */
static DynamicVectorClass Objectives;
diff -urN sourceold/scripts/dp88_custom_timer_defines.h source/scripts/dp88_custom_timer_defines.h
--- sourceold/scripts/dp88_custom_timer_defines.h 2018-11-17 10:23:57.147600000 +1000
+++ source/scripts/dp88_custom_timer_defines.h 2020-09-10 09:08:27.952893600 +1000
@@ -46,6 +46,7 @@
#define CUSTOM_ROCKETEER_VEHICLEKILLED (DP88_CUSTOM|MISC|0x03) //!< Used by dp88_AR_Rocketeer to notify itself when the flight vehicle dies (via JFW_Death_Send_Custom)
#define CUSTOM_VEHICLE_DEPLOY (DP88_CUSTOM|MISC|0x04) //!< Used by deployable vehicle scripts to notify other scripts of a change in the deployment state, 0 = undeployed, 1 = deploying, 2 = deployed, 3 = undeploying
#define CUSTOM_RADAR_JAM (DP88_CUSTOM|MISC|0x05) //!< Used by new Radar Jammer scripts to switch radar off and on and also play jamming sounds, 0 = radar off, 1 = radar on
+#define CUSTOM_DEPLOY_STATE_CHANGED (DP88_CUSTOM|MISC|0x07) //!< Used by deployable scripts to notify other scripts of a change in the deployment state, 0 = undeployed, 1 = deployed
#define TIMER_MISC_TICK (DP88_TIMER|MISC|0x01) //!< Miscellaneous tick timer for generic use by scripts that implement on-tick events
#define TIMER_RANDOMWEATHER (DP88_TIMER|MISC|0x02) //!< Used by dp88_randomWeather to do a weather update
@@ -136,6 +137,7 @@
//#define CUSTOM_TURRETAI_ANIMATIONCOMPLETE (DP88_CUSTOM|AI|0x02) //!< Sent from dp88_AI_ChargeTurret_Animation to dp88_AI_ChargeTurret
#define CUSTOM_AI_DISABLEAI (DP88_CUSTOM|AI|0x03) //!< Custom message that can be sent to a turret AI to disable it
#define CUSTOM_AI_ENABLEAI (DP88_CUSTOM|AI|0x04) //!< Custom message that can be sent to a turret AI to enable it
+#define CUSTOM_AI_RESET_ACTIONS (DP88_CUSTOM|AI|0x05) //!< Custom message that can be sent to an AI to reset its current actions
#define TIMER_AI_THINK (DP88_TIMER|AI|0x01) //!< Fires every second to process AI actions such as checking target status
#define TIMER_AI_CHARGE_PRERELOAD_COMPLETE (DP88_TIMER|AI|0x02) //!< Used by dp88_AI_ChargedTurret to indicate when pre-reloading is complete
@@ -171,6 +173,10 @@
#define CUSTOM_PRISMTOWER_STOP_CHARGING 1144060002
+// Custom for changing bot count on a map
+#define CUSTOM_AI_CHANGE_BOTCOUNT 1144062001
+#define CUSTOM_AI_CHANGE_BOTCOUNTTEAM 1144062002
+
#define TIMER_CLEG_PHASEDEATH 10055222
#define TIMER_CLEG_CHECKDROPOBJ 10055223
#define TIMER_CLEG_CHECKRELEASETARGET 10055224
diff -urN sourceold/scripts/engine_common.h source/scripts/engine_common.h
--- sourceold/scripts/engine_common.h 2018-11-17 10:23:57.154600000 +1000
+++ source/scripts/engine_common.h 2020-04-02 12:02:44.438361500 +1000
@@ -15,7 +15,7 @@
// (float) is merely there to make sure that it uses the float overloads to send the version over network.
// and to make sure we do not forget the f suffix on the version number.
#define TT_VERSION_MAGIC '!TT!'
-#define TT_VERSION ((float)4.6f)
+#define TT_VERSION ((float)4.7f)
#define SAFE_DELETE_ARRAY(p) { delete[] p; p = NULL; }
#define SAFE_DELETE(p) { delete p; p = NULL; }
diff -urN sourceold/scripts/engine_dmg.cpp source/scripts/engine_dmg.cpp
--- sourceold/scripts/engine_dmg.cpp 2018-11-17 10:23:57.156600000 +1000
+++ source/scripts/engine_dmg.cpp 2020-09-10 09:08:27.953899600 +1000
@@ -161,6 +161,20 @@
Commands->Set_Health(obj,health);
}
+void SCRIPTS_API Set_Max_Health_Without_Healing(GameObject *obj,float health)
+{
+ if (!obj)
+ {
+ return;
+ }
+ DamageableGameObj *o = obj->As_DamageableGameObj();
+ if (!o)
+ {
+ return;
+ }
+ o->Get_Defense_Object()->Set_Health_Max(health);
+}
+
void SCRIPTS_API Set_Max_Shield_Strength(GameObject *obj,float shieldstrength)
{
if (!obj)
@@ -176,6 +190,20 @@
Commands->Set_Shield_Strength(obj,shieldstrength);
}
+void SCRIPTS_API Set_Max_Shield_Strength_Without_Healing(GameObject *obj,float shieldstrength)
+{
+ if (!obj)
+ {
+ return;
+ }
+ DamageableGameObj *o = obj->As_DamageableGameObj();
+ if (!o)
+ {
+ return;
+ }
+ o->Get_Defense_Object()->Set_Shield_Strength_Max(shieldstrength);
+}
+
const char SCRIPTS_API *Get_Shield_Type(GameObject *obj)
{
if (!obj)
@@ -226,6 +254,8 @@
{
return;
}
+ Vector3 TestPosition = Position;
+ TestPosition.Z = 0;
SLNode *x = GameObjManager::VehicleGameObjList.Head();
while (x)
{
@@ -233,10 +263,9 @@
if (obj)
{
Vector3 ObjPosition = Commands->Get_Position(obj);
- Vector3 TestPosition = Position;
+
ObjPosition.Z = 0;
- TestPosition.Z = 0;
- if ((Commands->Get_Distance(ObjPosition,TestPosition) <= Distance) && (Commands->Get_ID(obj) != Commands->Get_ID(Host)))
+ if ((Vector3::Distance_Squared(ObjPosition, TestPosition) <= Distance * Distance) && (Commands->Get_ID(obj) != Commands->Get_ID(Host)))
{
Commands->Apply_Damage(obj,Damage,Warhead,Damager);
}
@@ -251,6 +280,8 @@
{
return;
}
+ Vector3 TestPosition = Position;
+ TestPosition.Z = 0;
SLNode *x = GameObjManager::GameObjList.Head();
while (x)
{
@@ -263,10 +294,8 @@
if (o2)
{
Vector3 ObjPosition = Commands->Get_Position(o2);
- Vector3 TestPosition = Position;
ObjPosition.Z = 0;
- TestPosition.Z = 0;
- if ((Commands->Get_Distance(ObjPosition,TestPosition) <= Distance) && (Commands->Get_ID(o2) != Commands->Get_ID(Host)))
+ if ((Vector3::Distance_Squared(ObjPosition, TestPosition) <= Distance * Distance) && (Commands->Get_ID(o2) != Commands->Get_ID(Host)))
{
Commands->Apply_Damage(o2,Damage,Warhead,Damager);
}
@@ -289,7 +318,7 @@
{
Vector3 ObjPosition = Commands->Get_Position(o);
Vector3 TestPosition = Position;
- if (Commands->Get_Distance(ObjPosition,TestPosition) <= Distance)
+ if (Vector3::Distance_Squared(ObjPosition, TestPosition) <= Distance * Distance)
{
Commands->Apply_Damage(o,Damage,Warhead,Damager);
}
@@ -316,9 +345,7 @@
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
-
- if (Distance <= DamageRadius)
+ if (Vector3::Distance_Squared(pos1, pos2) <= DamageRadius * DamageRadius)
{
Commands->Apply_Damage(o,Damage,Warhead,Damager);
}
@@ -377,9 +404,7 @@
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
-
- if (Distance <= DamageRadius)
+ if (Vector3::Distance_Squared(pos1, pos2) <= DamageRadius * DamageRadius)
{
float Max_Health = Commands->Get_Max_Health(o);
float Damage = Max_Health*Percentage;
@@ -409,8 +434,7 @@
{
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
- if (Distance <= DamageRadius)
+ if (Vector3::Distance_Squared(pos1, pos2) <= DamageRadius * DamageRadius)
{
Commands->Apply_Damage(o,Damage,Warhead,Damager);
}
@@ -472,8 +496,7 @@
{
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
- if (Distance <= DamageRadius)
+ if (Vector3::Distance_Squared(pos1, pos2) <= DamageRadius * DamageRadius)
{
float Max_Health = Commands->Get_Max_Health(o);
float Damage = Max_Health*Percentage;
@@ -517,8 +540,8 @@
{
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
- if (Distance <= DamageRadius)
+ float Distance = Vector3::Distance_Squared(pos1, pos2);
+ if (Distance <= DamageRadius * DamageRadius)
{
float Max_Health = Commands->Get_Max_Health(o);
float Max_Shield = Commands->Get_Max_Shield_Strength(o);
@@ -576,8 +599,8 @@
{
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
- if (Distance <= Radius)
+ float Distance = Vector3::Distance_Squared(pos1, pos2);
+ if (Distance <= Radius * Radius)
{
Commands->Set_Health(o,(amount+Health));
}
@@ -719,8 +742,8 @@
{
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1,pos2);
- if (Distance <= DamageRadius)
+ float Distance = Vector3::Distance_Squared(pos1, pos2);
+ if (Distance <= DamageRadius * DamageRadius)
{
float Max_Health = Commands->Get_Max_Health(o);
float Max_Shield = Commands->Get_Max_Shield_Strength(o);
@@ -767,8 +790,8 @@
{
Vector3 pos1 = Commands->Get_Position(o);
Vector3 pos2 = Location;
- float Distance = Commands->Get_Distance(pos1, pos2);
- if (Distance <= DamageRadius)
+ float Distance = Vector3::Distance_Squared(pos1, pos2);
+ if (Distance <= DamageRadius * DamageRadius)
{
float Max_Health = Commands->Get_Max_Health(o);
float Max_Shield = Commands->Get_Max_Shield_Strength(o);
diff -urN sourceold/scripts/engine_dmg.h source/scripts/engine_dmg.h
--- sourceold/scripts/engine_dmg.h 2016-10-31 07:17:12.471013500 +1000
+++ source/scripts/engine_dmg.h 2020-03-30 20:42:37.433301100 +1000
@@ -15,7 +15,9 @@
void SCRIPTS_API Repair_All_Buildings_By_Team(int Team,int ConstructionYardID,float Health); //repairs all buildings for the team except the passed in ConstructionYardID,0 = Nod,1 = GDI
void SCRIPTS_API Repair_All_Static_Vehicles_By_Team(int Team,int type); //sends a custom to all vechicles of the team with the DecorationPhys physics type (i.e. all base defense vechicles etc),0 = Nod,1 = GDI,Message is the message to send. Use with JFW_Repair_On_Custom on the vechicles you want repaired to do the actual repairing
void SCRIPTS_API Set_Max_Health(GameObject *obj,float health); //set the max health of obj
+void SCRIPTS_API Set_Max_Health_Without_Healing(GameObject *obj,float health); //set the max health of obj without setting the actual health to maximum
void SCRIPTS_API Set_Max_Shield_Strength(GameObject *obj,float shieldstrength); //set the max shield strength of obj
+void SCRIPTS_API Set_Max_Shield_Strength_Without_Healing(GameObject *obj,float shieldstrength); //set the max shield strength of obj without setting the actual health to maximum
const char SCRIPTS_API *Get_Shield_Type(GameObject *obj); //gets the shield type of obj
const char SCRIPTS_API *Get_Skin(GameObject *obj); //gets the skin type of obj
void SCRIPTS_API Set_Skin(GameObject *obj,const char *Skintype); //sets the skin type of obj
diff -urN sourceold/scripts/engine_io.cpp source/scripts/engine_io.cpp
--- sourceold/scripts/engine_io.cpp 2018-11-17 10:23:57.160600000 +1000
+++ source/scripts/engine_io.cpp 2020-09-10 09:08:27.953899600 +1000
@@ -565,6 +565,26 @@
strtrim(result);
return (int)strlen(result);
}
+int INIClass::Get_String_Advanced(char const *section,char const *entry,char const *defaultvalue,char *result,int size,bool updateIfNotFound) const
+{
+ if (!result || size <= 1 || !section || !entry)
+ return 0;
+ INIEntry *Entry = Find_Entry(section,entry);
+ const char *value = defaultvalue;
+ if (Entry && Entry->Value)
+ value = Entry->Value;
+ if ((!Entry || !Entry->Value) && !updateIfNotFound)
+ return 0;
+ if (!value)
+ {
+ result[0] = 0;
+ return 0;
+ }
+ strncpy(result, value, size);
+ result[size - 1] = 0;
+ strtrim(result);
+ return (int)strlen(result);
+}
int INIClass::Entry_Count(char const *section) const
{
INISection *Section = Find_Section(section);
diff -urN sourceold/scripts/engine_io.h source/scripts/engine_io.h
--- sourceold/scripts/engine_io.h 2018-11-17 10:23:57.161600000 +1000
+++ source/scripts/engine_io.h 2020-09-10 09:08:27.954910800 +1000
@@ -132,6 +132,7 @@
float Get_Float(char const *section,char const *entry,float defaultvalue) const;
bool Get_Bool(char const *section,char const *entry,bool defaultvalue) const;
int Get_String(char const *section,char const *entry,char const *defaultvalue,char *result,int size) const;
+ int Get_String_Advanced(char const *section,char const *entry,char const *defaultvalue,char *result,int size,bool writeIfNotFound) const;
StringClass &Get_String(StringClass &str, const char* section, const char* entry, const char* default = 0) const;
WideStringClass &Get_Wide_String(WideStringClass &,char const*,char const*,wchar_t const*) const;
bool Put_Wide_String(const char* section, const char* entry, const wchar_t* string);
diff -urN sourceold/scripts/engine_obj.cpp source/scripts/engine_obj.cpp
--- sourceold/scripts/engine_obj.cpp 2018-11-17 10:23:57.163600000 +1000
+++ source/scripts/engine_obj.cpp 2020-09-10 09:08:27.954910800 +1000
@@ -403,7 +403,7 @@
GameObject SCRIPTS_API *Find_Closest_Non_Building_Object_By_Team(int Team,Vector3 position)
{
- float closestdist = FLT_MAX;
+ float closestdist_sq = FLT_MAX;
GameObject *closest = 0;
SLNode *x = GameObjManager::GameObjList.Head();
while (x)
@@ -419,10 +419,10 @@
if ((Get_Object_Type(o2) == Team) && !o2->As_BuildingGameObj())
{
Vector3 pos = Commands->Get_Position(o2);
- float dist = Commands->Get_Distance(pos,position);
- if (dist < closestdist)
+ float dist_sq = Vector3::Distance_Squared(pos, position);
+ if (dist_sq < closestdist_sq)
{
- closestdist = dist;
+ closestdist_sq = dist_sq;
closest = o2;
}
}
@@ -434,7 +434,7 @@
GameObject SCRIPTS_API *Find_Closest_Preset_By_Team(int Team,const Vector3 &pos,const char *Preset)
{
- float closestdist = 9999.0f;
+ float closestdist_sq = FLT_MAX;
GameObject *closest = 0;
SLNode *x = GameObjManager::GameObjList.Head();
while (x)
@@ -449,10 +449,10 @@
{
if ((Get_Object_Type(o2) == Team || Team == 2) && !_stricmp(Commands->Get_Preset_Name(o2),Preset))
{
- float dist = Commands->Get_Distance(Commands->Get_Position(o2),pos);
- if (dist < closestdist)
+ float dist_sq = Vector3::Distance_Squared(Commands->Get_Position(o2), pos);
+ if (dist_sq < closestdist_sq)
{
- closestdist = dist;
+ closestdist_sq = dist_sq;
closest = o2;
}
}
@@ -558,6 +558,7 @@
GameObject SCRIPTS_API *Find_Nearest_Preset(Vector3 position, const char *preset)
{
GameObject *object = 0;
+ float min_dist_sq = FLT_MAX;
SLNode *x = GameObjManager::GameObjList.Head();
while (x)
{
@@ -571,18 +572,13 @@
{
if (!_stricmp(Commands->Get_Preset_Name(o2),preset))
{
- if (object)
- {
- Vector3 obj_pos = Commands->Get_Position(object);
- Vector3 o_pos = Commands->Get_Position(o2);
- if (Commands->Get_Distance(position, o_pos) < Commands->Get_Distance(position, obj_pos))
- {
- object = o2;
- }
- }
- else
+ Vector3 pos;
+ o2->Get_Position(&pos);
+ float dist_sq = Vector3::Distance_Squared(position, pos);
+ if (dist_sq < min_dist_sq)
{
object = o2;
+ min_dist_sq = dist_sq;
}
}
}
@@ -689,6 +685,8 @@
{
return;
}
+ Vector3 TestPosition = Position;
+ TestPosition.Z = 0;
SLNode *x = GameObjManager::GameObjList.Head();
while (x)
{
@@ -701,10 +699,8 @@
if (o2)
{
Vector3 ObjPosition = Commands->Get_Position(o2);
- Vector3 TestPosition = Position;
ObjPosition.Z = 0;
- TestPosition.Z = 0;
- if ((Commands->Get_Distance(ObjPosition,TestPosition) <= Distance))
+ if (Vector3::Distance_Squared(ObjPosition, TestPosition) <= Distance * Distance)
{
if ((Get_Object_Type(o2) == team) || (team == 2))
{
@@ -787,7 +783,7 @@
Vector3 pos = Commands->Get_Position(o2);
pos.Z = 0;
location.Z = 0;
- if (Commands->Get_Distance(pos,location) <= range)
+ if (Vector3::Distance_Squared(pos, location) <= range * range)
{
if (o2->As_VehicleGameObj() && !empty)
{
@@ -909,7 +905,7 @@
GameObject SCRIPTS_API *Get_Closest_Armed_Object_To_Object( GameObject* obj, int team )
{
- float closestdist = FLT_MAX;
+ float closestdist_sq = FLT_MAX;
GameObject *closest = 0;
Vector3 position = Commands->Get_Position(obj);
SLNode *x = GameObjManager::GameObjList.Head();
@@ -926,10 +922,10 @@
if ((team == 2 || Get_Object_Type(o2) == team) && o2->As_PhysicalGameObj() && o2->As_PhysicalGameObj()->As_ArmedGameObj())
{
Vector3 pos = Commands->Get_Position(o2);
- float dist = Commands->Get_Distance(pos,position);
- if (dist < closestdist)
+ float dist_sq = Vector3::Distance_Squared(pos, position);
+ if (dist_sq < closestdist_sq)
{
- closestdist = dist;
+ closestdist_sq = dist_sq;
closest = o2;
}
}
diff -urN sourceold/scripts/engine_obj2.cpp source/scripts/engine_obj2.cpp
--- sourceold/scripts/engine_obj2.cpp 2018-11-17 10:23:57.165600000 +1000
+++ source/scripts/engine_obj2.cpp 2020-09-10 09:08:27.955908400 +1000
@@ -33,14 +33,14 @@
AT2(0x006C6420,0x006C5CC0);
ScriptZoneGameObj *ScriptZoneGameObj::Find_Closest_Zone(Vector3 &Location,ZoneConstants::ZoneType Type)
{
- float closest = 999999;
+ float closest = FLT_MAX;
ScriptZoneGameObj *closestzone = 0;
for (SLNode* node = GameObjManager::ScriptZoneGameObjList.Head(); node; node = node->Next())
{
ScriptZoneGameObj *zone = node->Data();
if (zone->Get_Definition().Get_Type() == Type)
{
- float distance = Vector3::Distance(zone->Get_Bounding_Box().Center,Location);
+ float distance = Vector3::Distance_Squared(zone->Get_Bounding_Box().Center,Location);
if (distance < closest)
{
closest = distance;
diff -urN sourceold/scripts/engine_phys.cpp source/scripts/engine_phys.cpp
--- sourceold/scripts/engine_phys.cpp 2018-11-17 10:23:57.167600000 +1000
+++ source/scripts/engine_phys.cpp 2020-09-10 09:08:27.956842600 +1000
@@ -150,15 +150,15 @@
void SCRIPTS_API Create_Effect_All_Stealthed_Objects_Area(const Vector3 &Position,float Distance,const char *object,const Vector3 &offset,int team)
{
+ Vector3 TestPosition = Position;
+ TestPosition.Z = 0;
SLNode *x = GameObjManager::SmartGameObjList.Head();
while (x)
{
SmartGameObj *obj = x->Data();
Vector3 ObjPosition = Commands->Get_Position(obj);
- Vector3 TestPosition = Position;
ObjPosition.Z = 0;
- TestPosition.Z = 0;
- if ((Commands->Get_Distance(ObjPosition,TestPosition) <= Distance))
+ if ((Vector3::Distance_Squared(ObjPosition,TestPosition) <= Distance * Distance))
{
if ((Get_Object_Type(obj) == team) || (team == 2))
{
diff -urN sourceold/scripts/engine_player.cpp source/scripts/engine_player.cpp
--- sourceold/scripts/engine_player.cpp 2018-11-17 10:23:57.169600000 +1000
+++ source/scripts/engine_player.cpp 2020-03-28 21:10:59.023831800 +1000
@@ -76,10 +76,14 @@
{
return newstr("None");
}
- if (!((cPlayer *)o->Get_Player_Data()))
+ if (!((cPlayer *)o->Get_Player_Data()) && o->Get_Bot_Tag().Is_Empty())
{
return newstr("None");
}
+ if (!o->Get_Bot_Tag().Is_Empty())
+ {
+ return WideCharToChar(o->Get_Bot_Tag());
+ }
return WideCharToChar(((cPlayer *)o->Get_Player_Data())->Get_Name());
}
@@ -504,10 +508,14 @@
{
return L"None";
}
- if (!((cPlayer *)o->Get_Player_Data()))
+ if (!((cPlayer *)o->Get_Player_Data()) && o->Get_Bot_Tag().Is_Empty())
{
return L"None";
}
+ if (!o->Get_Bot_Tag().Is_Empty())
+ {
+ return o->Get_Bot_Tag().Peek_Buffer();
+ }
return ((cPlayer *)o->Get_Player_Data())->Get_Name().Peek_Buffer();
}
diff -urN sourceold/scripts/engine_pt.cpp source/scripts/engine_pt.cpp
--- sourceold/scripts/engine_pt.cpp 2018-11-17 10:23:57.171600000 +1000
+++ source/scripts/engine_pt.cpp 2020-09-10 09:08:27.956842600 +1000
@@ -15,10 +15,9 @@
#include "engine_def.h"
#include "engine_obj2.h"
-unsigned int SCRIPTS_API Get_Team_Cost(const char *preset,unsigned int team)
+unsigned int SCRIPTS_API Get_Team_Cost(int def_id,unsigned int team)
{
- int ID = Get_Definition_ID(preset);
- if (TeamPurchaseSettingsDefClass::Get_Definition((TeamPurchaseSettingsDefClass::TEAM)PTTEAM(team))->Get_Beacon_Definition() == ID)
+ if (TeamPurchaseSettingsDefClass::Get_Definition((TeamPurchaseSettingsDefClass::TEAM)PTTEAM(team))->Get_Beacon_Definition() == def_id)
{
return TeamPurchaseSettingsDefClass::Get_Definition((TeamPurchaseSettingsDefClass::TEAM)PTTEAM(team))->Get_Beacon_Cost();
}
@@ -29,7 +28,7 @@
{
for (unsigned int j = 0;j < 10;j++)
{
- if ((p->Get_Definition(j) == ID) || (p->Get_Alt_Definition(j,0) == ID) || (p->Get_Alt_Definition(j,1) == ID) || (p->Get_Alt_Definition(j,2) == ID))
+ if ((p->Get_Definition(j) == def_id) || (p->Get_Alt_Definition(j,0) == def_id) || (p->Get_Alt_Definition(j,1) == def_id) || (p->Get_Alt_Definition(j,2) == def_id))
{
return p->Get_Cost(j);
}
@@ -39,16 +38,26 @@
return 0;
}
-unsigned int SCRIPTS_API Get_Cost(const char *preset)
+unsigned int SCRIPTS_API Get_Team_Cost(const char *preset,unsigned int team)
+{
+ return Get_Team_Cost(Get_Definition_ID(preset), team);
+}
+
+unsigned int SCRIPTS_API Get_Cost(int def_id)
{
- unsigned int cost = Get_Team_Cost(preset,0);
+ unsigned int cost = Get_Team_Cost(def_id,0);
if (!cost)
{
- cost = Get_Team_Cost(preset,1);
+ cost = Get_Team_Cost(def_id,1);
}
return cost;
}
+unsigned int SCRIPTS_API Get_Cost(const char *preset)
+{
+ return Get_Cost(Get_Definition_ID(preset));
+}
+
void SCRIPTS_API Disable_Preset_By_Name(unsigned int Team,const char *Name, bool enable)
{
int ID = Get_Definition_ID(Name);
diff -urN sourceold/scripts/engine_pt.h source/scripts/engine_pt.h
--- sourceold/scripts/engine_pt.h 2018-11-17 10:23:57.172600000 +1000
+++ source/scripts/engine_pt.h 2020-09-10 09:08:27.957841300 +1000
@@ -14,7 +14,9 @@
#include "BuildingGameObjDef.h"
using namespace BuildingConstants;
unsigned int SCRIPTS_API Get_Team_Cost(const char *preset,unsigned int team); //Get the cost of a preset for a given team. Returns zero if the preset is not found in any of the purchase terminal data or if it is one of the free units.
+unsigned int SCRIPTS_API Get_Team_Cost(int def_id,unsigned int team); //Get the cost of a preset for a given team. Returns zero if the preset is not found in any of the purchase terminal data or if it is one of the free units.
unsigned int SCRIPTS_API Get_Cost(const char *preset); //Get the cost of a preset. Returns zero if the preset is not found in any of the purchase terminal data or if it is one of the free units.
+unsigned int SCRIPTS_API Get_Cost(int def_id); //Get the cost of a preset. Returns zero if the preset is not found in any of the purchase terminal data or if it is one of the free units.
void SCRIPTS_API Disable_Preset_By_Name(unsigned int Team,const char *Name, bool enable); //Disable a preset by name
void SCRIPTS_API Hide_Preset_By_Name(unsigned int Team,const char *Name, bool enable); //Hides a preset by name
void SCRIPTS_API Busy_Preset_By_Name(unsigned int Team,const char *Name, bool enable); //Marks a preset as busy by name
diff -urN sourceold/scripts/engine_script.cpp source/scripts/engine_script.cpp
--- sourceold/scripts/engine_script.cpp 2018-11-17 10:23:57.173600000 +1000
+++ source/scripts/engine_script.cpp 2020-09-10 09:08:27.958838700 +1000
@@ -11,6 +11,7 @@
*/
#include "general.h"
#include "scripts.h"
+#include "engine_script.h"
#include "engine_vector.h"
#include "ScriptableGameObj.h"
#include "slist.h"
@@ -418,7 +419,7 @@
SCRIPTS_API GameObject *Find_Closest_Object_With_Script(const char *script, Vector3 pos)
{
- float closestdist = 0.0f;
+ float closestdist = FLT_MAX;
GameObject *closest = NULL;
SLNode *x = GameObjManager::GameObjList.Head();
while (x)
@@ -433,8 +434,8 @@
{
if (Is_Script_Attached(o2, script))
{
- float dist = Commands->Get_Distance(Commands->Get_Position(o2),pos);
- if (closest == NULL || dist < closestdist)
+ float dist = Vector3::Distance_Squared(Commands->Get_Position(o2), pos);
+ if (dist < closestdist)
{
closestdist = dist;
closest = o2;
@@ -514,6 +515,50 @@
delete d->Data();
}
+SCRIPTS_API void Find_All_Vehicles_By_Distance(SList& objects, Vector3 position)
+{
+ objects.Remove_All();
+
+ // Internal list of distances, in the same order as GameObjects in objects
+ SList distances;
+
+ for ( SLNode* objNode = GameObjManager::GameObjList.Head(); objNode != NULL; objNode = objNode->Next() )
+ {
+ ScriptableGameObj* obj = (objNode->Data()) ? objNode->Data()->As_ScriptableGameObj() : NULL;
+ if ( obj && obj->As_VehicleGameObj() )
+ {
+ // SList cannot contain non-pointer types... stupid thing!
+ float* distance = new float;
+ *distance = Commands->Get_Distance(Commands->Get_Position(obj), position);
+
+ SLNode* d = distances.Head();
+ for ( SLNode* o = objects.Head();
+ d != NULL;
+ d = d->Next(), o = o->Next() )
+ {
+ if ( *distance < *d->Data() )
+ {
+ objects.insertBefore(obj, *o);
+ distances.insertBefore(distance, *d);
+ distance = NULL;
+ break;
+ }
+ }
+
+ // OK, all existing objects are closer than this one so add it to the end of the list
+ if ( distance != NULL )
+ {
+ objects.Add_Tail(obj);
+ distances.Add_Tail(distance);
+ }
+ }
+ }
+
+ // Clean up memory since SList insists on having heap objects...
+ for ( SLNode* d = distances.Head(); d != NULL; d = d->Next() )
+ delete d->Data();
+}
+
SCRIPTS_API void Send_Custom_Event_To_Objects_With_Script( GameObject *sender, const char *script, int message, int param, float delay )
{
if (!sender)
@@ -560,7 +605,7 @@
{
if ( Is_Script_Attached( o2, script )
&& Commands->Get_ID ( sender ) != Commands->Get_ID ( o2 )
- && Commands->Get_Distance ( Commands->Get_Position ( sender ), Commands->Get_Position ( o2 ) ) <= range )
+ && Vector3::Distance_Squared ( Commands->Get_Position ( sender ), Commands->Get_Position ( o2 ) ) <= range * range )
{
Commands->Send_Custom_Event(sender,o2,message,param,delay);
}
@@ -627,4 +672,48 @@
va_start ( vargs, params );
Attach_Script_V(pObj,script,params,vargs);
va_end(vargs);
-}
\ No newline at end of file
+}
+
+int Get_Param_Type(const char *str)
+{
+ for (int i = 0; i < PARAM_TYPE_COUNT; i++)
+ {
+ if (!lstrcmpiA(str, PARAM_TYPE_STRINGS[i]))
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+
+SCRIPTS_API void Get_Script_Parameters(const char *script, DynamicVectorClass ¶meters)
+{
+ parameters.Delete_All();
+ auto factory = ScriptRegistrar::GetScriptFactory(script);
+ if (!factory)
+ {
+ return;
+ }
+ char* working = newstr(factory->GetParamDescription());
+ char *param = strtok(working, ",");
+ while (param)
+ {
+ char *sname = param;
+ char *type = strchr(param, ':');
+ type[0] = '\0';
+ type++;
+ char *value = strrchr(param, '=');
+ if (value)
+ {
+ value[0] = '\0';
+ value++;
+ }
+ ScriptParameter p;
+ p.name = sname;
+ p.value = value;
+ p.type = Get_Param_Type(type);
+ parameters.Add(p);
+ param = strtok(nullptr, ",");
+ }
+ delete[] working;
+}
diff -urN sourceold/scripts/engine_script.h source/scripts/engine_script.h
--- sourceold/scripts/engine_script.h 2018-11-17 10:23:57.173600000 +1000
+++ source/scripts/engine_script.h 2020-03-28 21:10:59.024829200 +1000
@@ -12,6 +12,7 @@
#ifndef SCRIPTS_INCLUDE__ENGINE_SCRIPT_H
#define SCRIPTS_INCLUDE__ENGINE_SCRIPT_H
#include "scripts.h"
+#include "engine_string.h"
#include "SList.h"
SCRIPTS_API void Remove_Script(GameObject *obj,const char *script); //removes all copies of