diff -urN sourceold/example-plugin/ExamplePlugin.cpp source/example-plugin/ExamplePlugin.cpp --- sourceold/example-plugin/ExamplePlugin.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/example-plugin/ExamplePlugin.cpp 2024-03-21 19:56:18.881555800 -0500 @@ -114,22 +114,22 @@ return true; } -int ExamplePlugin::OnPowerupPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus ExamplePlugin::OnPowerupPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { Console_Output(__FUNCTION__ "\n"); - return -1; + return PurchaseStatus_Allow; } -int ExamplePlugin::OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus ExamplePlugin::OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { Console_Output(__FUNCTION__ "\n"); - return -1; + return PurchaseStatus_Allow; } -int ExamplePlugin::OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus ExamplePlugin::OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { Console_Output(__FUNCTION__ "\n"); - return -1; + return PurchaseStatus_Allow; } void ExamplePlugin::OnThink() diff -urN sourceold/example-plugin/ExamplePlugin.h source/example-plugin/ExamplePlugin.h --- sourceold/example-plugin/ExamplePlugin.h 2024-03-08 20:25:22.000000000 -0600 +++ source/example-plugin/ExamplePlugin.h 2024-03-21 19:56:18.881555800 -0500 @@ -36,9 +36,9 @@ virtual void OnPlayerJoin(int PlayerID,const char *PlayerName); virtual void OnPlayerLeave(int PlayerID); virtual bool OnRefill(GameObject *purchaser); - virtual int OnPowerupPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); - virtual int OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); - virtual int OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + virtual PurchaseStatus OnPowerupPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + virtual PurchaseStatus OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + virtual PurchaseStatus OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); virtual void OnThink(); virtual void OnDialog(int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType); diff -urN sourceold/scripts/dllmain.cpp source/scripts/dllmain.cpp --- sourceold/scripts/dllmain.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/dllmain.cpp 2024-03-21 19:56:18.975302100 -0500 @@ -473,6 +473,8 @@ Get_Time_Of_Day = (gtod)Address(tt, "Get_Time_Of_Day"); Set_Time_Of_Day = (stod)Address(tt, "Set_Time_Of_Day"); Is_Connection_Bad = (icbad)Address(tt, "Is_Connection_Bad"); + Forward_Server = (fws)Address(tt, "Forward_Server"); + Add_Shadow_Message = (asmsg)Address(tt, "Add_Shadow_Message"); #ifdef SSGM SSGMGameManager::Init(); diff -urN sourceold/scripts/engine_tt.cpp source/scripts/engine_tt.cpp --- sourceold/scripts/engine_tt.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/engine_tt.cpp 2024-03-21 19:56:18.990927000 -0500 @@ -324,6 +324,8 @@ SCRIPTS_API gtod Get_Time_Of_Day; SCRIPTS_API stod Set_Time_Of_Day; SCRIPTS_API icbad Is_Connection_Bad; +SCRIPTS_API fws Forward_Server; +SCRIPTS_API asmsg Add_Shadow_Message; SCRIPTS_API bool Can_Team_Build_Vehicle(int Team) { diff -urN sourceold/scripts/engine_tt.h source/scripts/engine_tt.h --- sourceold/scripts/engine_tt.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/engine_tt.h 2024-03-21 19:56:18.990927000 -0500 @@ -258,6 +258,8 @@ typedef void (*gtod) (unsigned int* hours, unsigned int* minutes); typedef void (*stod) (unsigned int hours, unsigned int minutes); typedef bool (*icbad) (int playerID); +typedef void (*fws) (int client, int address, int port, const char* password); +typedef void (*asmsg) (int client, Vector3 color, const wchar_t* message); SCRIPTS_API extern gpl Get_Player_List; SCRIPTS_API extern gcmi Get_Current_Map_Index; SCRIPTS_API extern gm Get_Map; @@ -539,6 +541,8 @@ SCRIPTS_API extern gtod Get_Time_Of_Day; SCRIPTS_API extern stod Set_Time_Of_Day; SCRIPTS_API extern icbad Is_Connection_Bad; +SCRIPTS_API extern fws Forward_Server; +SCRIPTS_API extern asmsg Add_Shadow_Message; class SCRIPTS_API JFW_Key_Hook_Base : public ScriptImpClass { public: diff -urN sourceold/scripts/engine_ttdef.h source/scripts/engine_ttdef.h --- sourceold/scripts/engine_ttdef.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/engine_ttdef.h 2024-03-21 19:56:18.990927000 -0500 @@ -30,6 +30,17 @@ ANNOUNCE_TEAM, ANNOUNCE_PRIVATE, }; +enum PurchaseStatus +{ + PurchaseStatus_AllowNoSpawn = -3, // Purchase is allowed as normal, without spawning the vehicle. (only for VehiclePurchaseHook) + PurchaseStatus_AllowFree = -2, // Purchase is allowed as normal, without charging the player. + PurchaseStatus_Allow = -1, // Purchase is allowed as normal. + PurchaseStatus_Granted, // "Purchase request granted." + PurchaseStatus_Pending, // "Transaction pending." + PurchaseStatus_InsufficientFunds, // "You have insufficient funds for this purchase." + PurchaseStatus_FactoryUnavailable, // "The factory is not presently available." + PurchaseStatus_OutOfStock, // "This item is not presently in stock." +}; enum DialogMessageType { MESSAGE_TYPE_DIALOG_SHOW, // gets called when the dialog is shown @@ -47,7 +58,7 @@ typedef void (*PlayerLeave) (int PlayerID); typedef void (*LoadLevelHook) (); typedef void (*ConsoleOutputHook) (const char *output); -typedef int (*PurchaseHook) (BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); +typedef PurchaseStatus (*PurchaseHook) (BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); typedef void (*PurchaseMonHook) (BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,unsigned int purchaseret,const char *data); typedef bool (*RefillHook) (GameObject *purchaser); typedef bool (*RadioHook) (int PlayerType, int PlayerID, int AnnouncementID, int IconID, AnnouncementEnum AnnouncementType); diff -urN sourceold/scripts/gmgame.cpp source/scripts/gmgame.cpp --- sourceold/scripts/gmgame.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/gmgame.cpp 2024-03-21 19:56:18.990927000 -0500 @@ -965,11 +965,11 @@ return true; } -int SSGMGameManager::PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus SSGMGameManager::PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { if (IsPresetDisabled(preset) || DisableBeacons) { - return 4; + return PurchaseStatus_OutOfStock; } StringClass str; const char *str2 = Get_Translated_Definition_Name_Ini(Get_Definition_Name(preset)); @@ -982,28 +982,28 @@ bool fp = FreePurchases; for (int i = 0;i < RegisteredEvents[EVENT_POWERUP_PURCHASE_HOOK].Count();i++) { - int ret = RegisteredEvents[EVENT_POWERUP_PURCHASE_HOOK][i]->OnPowerupPurchase(base,purchaser,cost,preset,data); - if (ret == -2) + PurchaseStatus ret = RegisteredEvents[EVENT_POWERUP_PURCHASE_HOOK][i]->OnPowerupPurchase(base,purchaser,cost,preset,data); + if (ret == PurchaseStatus_AllowFree) { fp = true; } - else if (ret != -1) + else if (ret != PurchaseStatus_Allow) { return ret; } } if (fp) { - return -2; + return PurchaseStatus_AllowFree; } - return -1; + return PurchaseStatus_Allow; } -int SSGMGameManager::VehiclePurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus SSGMGameManager::VehiclePurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { if (IsPresetDisabled(preset)) { - return 4; + return PurchaseStatus_OutOfStock; } StringClass str; const char *str2 = Get_Translated_Definition_Name_Ini(Get_Definition_Name(preset)); @@ -1016,36 +1016,36 @@ bool fp = FreePurchases; for (int i = 0;i < RegisteredEvents[EVENT_VEHICLE_PURCHASE_HOOK].Count();i++) { - int ret = RegisteredEvents[EVENT_VEHICLE_PURCHASE_HOOK][i]->OnVehiclePurchase(base,purchaser,cost,preset,data); - if (ret == -2) + PurchaseStatus ret = RegisteredEvents[EVENT_VEHICLE_PURCHASE_HOOK][i]->OnVehiclePurchase(base,purchaser,cost,preset,data); + if (ret == PurchaseStatus_AllowFree) { fp = true; } - else if (ret != -1) + else if (ret != PurchaseStatus_Allow) { return ret; } } if (fp) { - return -2; + return PurchaseStatus_AllowFree; } - return -1; + return PurchaseStatus_Allow; } -int SSGMGameManager::CharacterPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus SSGMGameManager::CharacterPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { SSGM_Soldier *script = (SSGM_Soldier *)Find_Script_On_Object(purchaser,"SSGM_Soldier"); if (script && RefillLimit) { if (The_Game()->Get_Game_Duration_S() - script->RefillTime < RefillLimit) { - return 4; + return PurchaseStatus_OutOfStock; } } if (IsPresetDisabled(preset)) { - return 4; + return PurchaseStatus_OutOfStock; } StringClass str; const char *str2 = Get_Translated_Definition_Name_Ini(Get_Definition_Name(preset)); @@ -1058,21 +1058,21 @@ bool fp = FreePurchases; for (int i = 0;i < RegisteredEvents[EVENT_CHARACTER_PURCHASE_HOOK].Count();i++) { - int ret = RegisteredEvents[EVENT_CHARACTER_PURCHASE_HOOK][i]->OnCharacterPurchase(base,purchaser,cost,preset,data); - if (ret == -2) + PurchaseStatus ret = RegisteredEvents[EVENT_CHARACTER_PURCHASE_HOOK][i]->OnCharacterPurchase(base,purchaser,cost,preset,data); + if (ret == PurchaseStatus_AllowFree) { fp = true; } - else if (ret != -1) + else if (ret != PurchaseStatus_Allow) { return ret; } } if (fp) { - return -2; + return PurchaseStatus_AllowFree; } - return -1; + return PurchaseStatus_Allow; } void SSGMGameManager::ConsoleOutputHook(const char *output) diff -urN sourceold/scripts/gmgame.h source/scripts/gmgame.h --- sourceold/scripts/gmgame.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/gmgame.h 2024-03-21 19:56:18.990927000 -0500 @@ -28,9 +28,9 @@ static bool RefillHook(GameObject *purchaser); static void PlayerJoinHook(int PlayerID,const char *PlayerName); static void PlayerLeaveHook(int PlayerID); - static int PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); - static int VehiclePurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); - static int CharacterPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + static PurchaseStatus PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + static PurchaseStatus VehiclePurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + static PurchaseStatus CharacterPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); static void ReadConfig(INIClass *SSGMIni = NULL); static void ReadMapConfig(); static void FreeData(); diff -urN sourceold/scripts/gmplugin.h source/scripts/gmplugin.h --- sourceold/scripts/gmplugin.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/gmplugin.h 2024-03-21 19:56:18.990927000 -0500 @@ -52,9 +52,9 @@ virtual void OnPlayerJoin(int PlayerID,const char *PlayerName) {}; //called on player join virtual void OnPlayerLeave(int PlayerID) {}; //called on player leave virtual bool OnRefill(GameObject *purchaser) {return true;}; //called on refill - virtual int OnPowerupPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) {return -1;}; //called on beacon purchase - virtual int OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) {return -1;}; //called on vehicle purchase - virtual int OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) {return -1;}; //called on character purchase + virtual PurchaseStatus OnPowerupPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) {return PurchaseStatus_Allow;}; //called on beacon purchase + virtual PurchaseStatus OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) {return PurchaseStatus_Allow;}; //called on vehicle purchase + virtual PurchaseStatus OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) {return PurchaseStatus_Allow;}; //called on character purchase virtual void OnThink() {}; //called once per frame virtual bool OnRadioCommand(int PlayerType, int PlayerID, int AnnouncementID, int IconID, AnnouncementEnum AnnouncementType) {return true;} //called on radio command virtual bool OnStockDamage(PhysicalGameObj* damager, PhysicalGameObj* target, float damage, uint warheadId) { return true; } //called on damage from clients with version <4.0 diff -urN sourceold/scripts/jfwdmg.cpp source/scripts/jfwdmg.cpp --- sourceold/scripts/jfwdmg.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/jfwdmg.cpp 2024-03-21 19:56:19.006551300 -0500 @@ -1297,13 +1297,13 @@ } } -int JFW_Beacon_Building::PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) +PurchaseStatus JFW_Beacon_Building::PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data) { if (((GameObject *)data)->As_BuildingGameObj() && ((GameObject *)data)->As_BuildingGameObj()->Is_Destroyed() && ((GameObject *)data)->As_BuildingGameObj()->Get_Player_Type() == Commands->Get_Player_Type(purchaser)) { - return 3; + return PurchaseStatus_FactoryUnavailable; } - return -1; + return PurchaseStatus_Allow; } void JFW_Spawn_Object_Repair::Damaged(GameObject *obj,GameObject *damager,float amount) diff -urN sourceold/scripts/jfwdmg.h source/scripts/jfwdmg.h --- sourceold/scripts/jfwdmg.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/jfwdmg.h 2024-03-21 19:56:19.006551300 -0500 @@ -440,7 +440,7 @@ class JFW_Beacon_Building : public ScriptImpClass { int pos; void Created(GameObject *obj); - static int PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); + static PurchaseStatus PowerupPurchaseHook(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); public: JFW_Beacon_Building() {pos = 0;} ~JFW_Beacon_Building(); diff -urN sourceold/scripts/jmgUtility.cpp source/scripts/jmgUtility.cpp --- sourceold/scripts/jmgUtility.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/jmgUtility.cpp 2024-03-21 19:56:19.022176400 -0500 @@ -10342,16 +10342,22 @@ custom = Get_Int_Parameter("SendCustom"); Param = Get_Int_Parameter("Param"); delay = Get_Float_Parameter("Delay"); + maxDistance = Get_Float_Parameter("MaxDistance")*Get_Float_Parameter("MaxDistance"); } void JMG_Utility_Custom_Send_Custom_To_All_Objects::Custom(GameObject *obj,int message,int param,GameObject *sender) { if (message == recieveMessage) { + Vector3 pos = Commands->Get_Position(obj); for (SLNode *current = GameObjManager::GameObjList.Head();current;current = current->Next()) { GameObject* o = current->Data()->As_ScriptableGameObj(); if (o && (team == 2 || CheckPlayerType(o,team))) + { + if (maxDistance && JmgUtility::SimpleDistance(pos,Commands->Get_Position(o)) > maxDistance) + continue; Commands->Send_Custom_Event(obj,o,custom,Param == -1 ? param : Param,delay); + } } } } @@ -18434,7 +18440,73 @@ Commands->Start_Timer(obj,this,0.1f,2); } } +void JMG_Utility_Killed_Send_Custom::Killed(GameObject *obj,GameObject *killer) +{ + int id = Get_Int_Parameter("ID"); + GameObject *object = id ? (id == -1 ? killer : Commands->Find_Object(id)) : obj; + Commands->Send_Custom_Event(obj,object,Get_Int_Parameter("Custom"),Get_Int_Parameter("Param"),Get_Float_Parameter("Delay")); + Destroy_Script(); +} +void JMG_Utility_Killed_Send_Custom_Killer::Killed(GameObject *obj,GameObject *killer) +{ + int id = Get_Int_Parameter("ID"); + GameObject *object = id ? (id == -1 ? killer : Commands->Find_Object(id)) : obj; + Commands->Send_Custom_Event(killer,object,Get_Int_Parameter("Custom"),Get_Int_Parameter("Param"),Get_Float_Parameter("Delay")); + Destroy_Script(); +} +void JMG_Utility_Custom_Send_Custom_To_All_Objects_Sender::Created(GameObject *obj) +{ + recieveMessage = Get_Int_Parameter("Custom"); + team = Get_Int_Parameter("Team"); + custom = Get_Int_Parameter("SendCustom"); + Param = Get_Int_Parameter("Param"); + delay = Get_Float_Parameter("Delay"); + maxDistance = Get_Float_Parameter("MaxDistance")*Get_Float_Parameter("MaxDistance"); +} +void JMG_Utility_Custom_Send_Custom_To_All_Objects_Sender::Custom(GameObject *obj,int message,int param,GameObject *sender) +{ + if (message == recieveMessage) + { + Vector3 pos = Commands->Get_Position(obj); + for (SLNode *current = GameObjManager::GameObjList.Head();current;current = current->Next()) + { + GameObject* o = current->Data()->As_ScriptableGameObj(); + if (o && (team == 2 || CheckPlayerType(o,team))) + { + if (maxDistance && JmgUtility::SimpleDistance(pos,Commands->Get_Position(o)) > maxDistance) + continue; + Commands->Send_Custom_Event(sender,o,custom,Param == -1 ? param : Param,delay); + } + } + } +} +void JMG_Utility_Created_Fire_Randomly::Created(GameObject *obj) +{ + rate = Get_Float_Parameter("UpdateRate"); + angle = Get_Float_Parameter("FireAngle")*0.5f; + minHeight = Get_Float_Parameter("MinHeight"); + maxHeight = Get_Float_Parameter("MaxHeight"); + useFacing = Get_Float_Parameter("UseFacing"); + Commands->Start_Timer(obj,this,rate,1); +} +void JMG_Utility_Created_Fire_Randomly::Timer_Expired(GameObject *obj,int number) +{ + if (number == 1) + { + ActionParamsStruct params; + Commands->Get_Action_Params(obj,params); + Vector3 pos = Commands->Get_Position(obj); + float turretAngle = (angle > 0 ? Commands->Get_Random(-angle,angle) : 0.0f)+(useFacing != -999.0f ? useFacing : Commands->Get_Facing(obj)); + pos.X += cos(turretAngle*PI180)*100.0f; + pos.Y += sin(turretAngle*PI180)*100.0f; + pos.Z += minHeight < maxHeight ? Commands->Get_Random(minHeight,maxHeight) : minHeight; + params.AttackLocation = pos; + params.AttackForceFire = true; + Commands->Action_Attack(obj,params); + Commands->Start_Timer(obj,this,rate,1); + } +} ScriptRegistrant JMG_Utility_Check_If_Script_Is_In_Library_Registrant("JMG_Utility_Check_If_Script_Is_In_Library","ScriptName:string,CppName:string"); ScriptRegistrant JMG_Send_Custom_When_Custom_Sequence_Matched_Registrant("JMG_Send_Custom_When_Custom_Sequence_Matched","Success_Custom=0:int,Correct_Step_Custom=0:int,Partial_Failure_Custom=0:int,Failure_Custom=0:int,Send_To_ID=0:int,Custom_0=0:int,Custom_1=0:int,Custom_2=0:int,Custom_3=0:int,Custom_4=0:int,Custom_5=0:int,Custom_6=0:int,Custom_7=0:int,Custom_8=0:int,Custom_9=0:int,Disable_On_Success=1:int,Disable_On_Failure=0:int,Starts_Enabled=1:int,Enable_Custom=0:int,Correct_Step_Saftey=0:int,Failure_Saftey=1:int,Max_Failures=1:int"); ScriptRegistrant JMG_Utility_Change_Model_On_Timer_Registrant("JMG_Utility_Change_Model_On_Timer","Model=null:string,Time=0:float"); @@ -18678,7 +18750,7 @@ ScriptRegistrant JMG_Utility_Custom_Set_Position_Registrant("JMG_Utility_Custom_Set_Position","Custom:int,Position:Vector3,ID=0:int"); ScriptRegistrant JMG_Utility_Custom_Delay_Send_Custom_Registrant("JMG_Utility_Custom_Delay_Send_Custom","Custom:int,ID=0:int,SendCustom:int,Param:int,Delay:float,RandomDelay:float,CancelCustom=0:int"); ScriptRegistrant JMG_Utility_Scale_HP_By_Player_Count_Registrant("JMG_Utility_Scale_HP_By_Player_Count","Health_Multiplier=1.0:float,Armor_Multiplier=1.0:float,Max_Player_Count=-1:int,Repeat=1:int,UpdateScaleCustom=0:int"); -ScriptRegistrant JMG_Utility_Custom_Send_Custom_To_All_Objects_Registrant("JMG_Utility_Custom_Send_Custom_To_All_Objects","Custom:int,SendCustom:int,Param:int,Team=2:int,Delay=0.0:float"); +ScriptRegistrant JMG_Utility_Custom_Send_Custom_To_All_Objects_Registrant("JMG_Utility_Custom_Send_Custom_To_All_Objects","Custom:int,SendCustom:int,Param:int,Team=2:int,Delay=0.0:float,MaxDistance=0.0:float"); ScriptRegistrant JMG_Utility_Enemy_Seen_Send_Custom_Ignore_Registrant("JMG_Utility_Enemy_Seen_Send_Custom_Ignore",""); ScriptRegistrant JMG_Utility_In_Line_Of_Sight_Send_Custom_Registrant("JMG_Utility_In_Line_Of_Sight_Send_Custom","Enemy_Preset_ID:int,ID:int,Visible_Message:int,Visible_Param:int,Not_Visible_Message:int,Not_Visible_Param:int,Scan_Rate=0.1:float,Enemy_Only=1:int"); ScriptRegistrant JMG_Utility_In_Line_Of_Sight_Send_Custom_Ignore_Registrant("JMG_Utility_In_Line_Of_Sight_Send_Custom_Ignore",""); @@ -18883,3 +18955,7 @@ ScriptRegistrant JMG_Utility_Send_Custom_When_HP_Crosses_Threshold_Registrant("JMG_Utility_Send_Custom_When_HP_Crosses_Threshold","TargetRatio:float,ID:int,AboveCustom:int,AboveParam:int,BelowCustom:int,BelowParam:int"); ScriptRegistrant JMG_Utility_Change_SkinType_To_Blamo_Until_Damaged_Registrant("JMG_Utility_Change_SkinType_To_Blamo_Until_Damaged","MinHealthRatio=1.0:float"); ScriptRegistrant JMG_Utility_Send_Custom_When_Moved_Distance_From_Spawn_Registrant("JMG_Utility_Send_Custom_When_Moved_Distance_From_Spawn","Distance:float,ID:int,Custom:int,Param:int,StartDelay=0.0:float,RequireInPathfind=0:int"); +ScriptRegistrant JMG_Utility_Killed_Send_Custom_Registrant("JMG_Utility_Killed_Send_Custom","ID:int,Custom:int,Param:int,Delay:float"); +ScriptRegistrant JMG_Utility_Killed_Send_Custom_Killer_Registrant("JMG_Utility_Killed_Send_Custom_Killer","ID:int,Custom:int,Param:int,Delay:float"); +ScriptRegistrant JMG_Utility_Custom_Send_Custom_To_All_Objects_Sender_Registrant("JMG_Utility_Custom_Send_Custom_To_All_Objects_Sender","Custom:int,SendCustom:int,Param:int,Team=2:int,Delay=0.0:float,MaxDistance=0.0:float"); +ScriptRegistrant JMG_Utility_Created_Fire_Randomly_Registrant("JMG_Utility_Created_Fire_Randomly","FireAngle=45.0:float,MinHeight=0:float,MaxHeight=0:float,UpdateRate=1.5:float,UseFacing=-999.0:float"); diff -urN sourceold/scripts/jmgUtility.h source/scripts/jmgUtility.h --- sourceold/scripts/jmgUtility.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/jmgUtility.h 2024-03-21 19:56:19.022176400 -0500 @@ -7232,6 +7232,7 @@ * \SendCustom - custom to send * \Param - param to send (-1 sends the param that was received) * \Delay - delay to add +* \MaxDistance - 0 send to everyone, otherwise they must be in the range of the attached object * \author jgray * \ingroup JmgUtility */ @@ -7241,6 +7242,7 @@ int custom; int Param; float delay; + float maxDistance; void Created(GameObject *obj); void Custom(GameObject *obj,int message,int param,GameObject *sender); }; @@ -12256,4 +12258,72 @@ bool requireInPathfind; void Created(GameObject *obj); void Timer_Expired(GameObject *obj,int number); +}; + +/*! +* \brief Sends a custom message when killed +* \ID - Id of the object to send the custom to, 0 sends to itself, -1 to killer +* \Message - Custom to send +* \Param - parameter to send with the custom +* \Delay - Time amount to wait before sending the custom +* \author jgray +* \ingroup JmgUtility +*/ +class JMG_Utility_Killed_Send_Custom : public ScriptImpClass { + void Killed(GameObject *obj,GameObject *killer); +}; + +/*! +* \brief Sends a custom message when killed from the killer +* \ID - Id of the object to send the custom to, 0 sends to itself, -1 to killer +* \Message - Custom to send +* \Param - parameter to send with the custom +* \Delay - Time amount to wait before sending the custom +* \author jgray +* \ingroup JmgUtility +*/ +class JMG_Utility_Killed_Send_Custom_Killer : public ScriptImpClass { + void Killed(GameObject *obj,GameObject *killer); +}; + +/*! +* \brief Sends a to all objects on the map sends from the sender +* \Custom - Custom to watch for +* \Team - Required team to send to, 2 for any +* \SendCustom - custom to send +* \Param - param to send (-1 sends the param that was received) +* \Delay - delay to add +* \MaxDistance - 0 send to everyone, otherwise they must be in the range of the attached object +* \author jgray +* \ingroup JmgUtility +*/ +class JMG_Utility_Custom_Send_Custom_To_All_Objects_Sender : public ScriptImpClass { + int recieveMessage; + int team; + int custom; + int Param; + float delay; + float maxDistance; + void Created(GameObject *obj); + void Custom(GameObject *obj,int message,int param,GameObject *sender); +}; + +/*! +* \brief Sends a custom message when the attached object moves a distance from its initial spawn location +* \FireAngle - Random angle off the objects current facing to fire at +* \MinHeight - Lowest point off the current position to aim at +* \MaxHeight - Highest point off the current position to aim at +* \UpdateRate - How long between each aim update to wait +* \UseFacing - If -999 it will use the current rotation, otherwise the math will be done off the facing you enter here +* \author jgray +* \ingroup JmgUtility +*/ +class JMG_Utility_Created_Fire_Randomly : public ScriptImpClass { + float rate; + float angle; + float minHeight; + float maxHeight; + float useFacing; + void Created(GameObject *obj); + void Timer_Expired(GameObject *obj,int number); }; \ No newline at end of file diff -urN sourceold/scripts/mdbevf.cpp source/scripts/mdbevf.cpp --- sourceold/scripts/mdbevf.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/mdbevf.cpp 2024-03-21 19:56:19.022176400 -0500 @@ -915,16 +915,16 @@ Flying_Landing_Positions = 0; Loaded = false; } -int ExpVehFacClass::Purchase_Hook(BaseControllerClass *base, GameObject *purchaser, unsigned int cost, unsigned int preset,const char *data) +PurchaseStatus ExpVehFacClass::Purchase_Hook(BaseControllerClass *base, GameObject *purchaser, unsigned int cost, unsigned int preset,const char *data) { int Team = Get_Object_Type(purchaser); if (!ExpVehFac[Team] || !ExpVehFac[Team]->Loaded) { - return -1; + return PurchaseStatus_Allow; } if (!Can_Team_Build_Vehicle(Team) || cost >= 100000 || !preset) { - return 3; + return PurchaseStatus_FactoryUnavailable; } UnitInfo *Temp = ExpVehFac[Team]->Get_Unit_Info(preset); if (Temp->VehType == VEHTYPE_NAVAL) @@ -934,17 +934,17 @@ if (ExpVehFac[Team]->Support_Limit && ExpVehFac[Team]->Support_Amount >= ExpVehFac[Team]->Support_Limit) { Send_Message_Player(purchaser,255,255,255,"The limit for Support vehicles has been reached."); - return 3; + return PurchaseStatus_FactoryUnavailable; } } else if (ExpVehFac[Team]->Naval_Limit && ExpVehFac[Team]->Naval_Amount >= ExpVehFac[Team]->Naval_Limit) { Send_Message_Player(purchaser,255,255,255,"The limit for Naval vehicles has been reached."); - return 3; + return PurchaseStatus_FactoryUnavailable; } if (ExpVehFac[Team]->Is_Naval_Building) { - return 3; + return PurchaseStatus_FactoryUnavailable; } else if (Purchase_Item(purchaser,cost)) { @@ -965,9 +965,9 @@ GameObject *Veh = Commands->Create_Object(Get_Definition_Name(preset),Pos); Commands->Set_Facing(Veh,Commands->Get_Facing(obj)); Commands->Send_Custom_Event(Veh,Veh,CUSTOM_EVENT_VEHICLE_OWNER,Commands->Get_ID(purchaser),0); - return 0; + return PurchaseStatus_Granted; } - return 2; + return PurchaseStatus_InsufficientFunds; } else if (Temp->VehType == VEHTYPE_FLYING) { @@ -976,17 +976,17 @@ if (ExpVehFac[Team]->Support_Limit && ExpVehFac[Team]->Support_Amount >= ExpVehFac[Team]->Support_Limit) { Send_Message_Player(purchaser,255,255,255,"The limit for Support vehicles has been reached."); - return 3; + return PurchaseStatus_FactoryUnavailable; } } else if (ExpVehFac[Team]->Flying_Limit && ExpVehFac[Team]->Flying_Amount >= ExpVehFac[Team]->Flying_Limit) { Send_Message_Player(purchaser,255,255,255,"The limit for Flying vehicles has been reached."); - return 3; + return PurchaseStatus_FactoryUnavailable; } if (ExpVehFac[Team]->Is_Flying_Building) { - return 3; + return PurchaseStatus_FactoryUnavailable; } else if (Purchase_Item(purchaser,cost)) { @@ -1003,9 +1003,9 @@ ExpVehFac[Team]->LastFlyVehID = preset; ExpVehFac[Team]->LastFlyVehOwner = Commands->Get_ID(purchaser); Commands->Attach_Script(Commands->Create_Object("Invisible_Object",ExpVehFac[Team]->Get_Flying_Landing_Position()),"Test_Cinematic",Team?"ExpVehFac_1.txt":"ExpVehFac_0.txt"); - return 0; + return PurchaseStatus_Granted; } - return 2; + return PurchaseStatus_InsufficientFunds; } else { @@ -1014,17 +1014,17 @@ if (ExpVehFac[Team]->Support_Limit && ExpVehFac[Team]->Support_Amount >= ExpVehFac[Team]->Support_Limit) { Send_Message_Player(purchaser,255,255,255,"The limit for Support vehicles has been reached."); - return 3; + return PurchaseStatus_FactoryUnavailable; } } else if (ExpVehFac[Team]->Ground_Limit && ExpVehFac[Team]->Ground_Amount >= ExpVehFac[Team]->Ground_Limit) { Send_Message_Player(purchaser,255,255,255,"The limit for Ground vehicles has been reached."); - return 3; + return PurchaseStatus_FactoryUnavailable; } if (ExpVehFac[Team]->Is_Ground_Building) { - return 3; + return PurchaseStatus_FactoryUnavailable; } else if (Purchase_Item(purchaser,cost)) { @@ -1039,9 +1039,9 @@ ExpVehFac[Team]->Set_Ground_Currently_Building(true); Commands->Send_Custom_Event(0,ExpVehFac[Team]->Script,129313,Team,ExpVehFac[Team]->Ground_Build_Time[1]); } - return 0; + return PurchaseStatus_Granted; } - return 2; + return PurchaseStatus_InsufficientFunds; } } void ExpVehFacClass::Object_Hook(void *,GameObject *obj) diff -urN sourceold/scripts/mdbevf.h source/scripts/mdbevf.h --- sourceold/scripts/mdbevf.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/mdbevf.h 2024-03-21 19:56:19.022176400 -0500 @@ -89,7 +89,7 @@ UnitInfo *Get_Unit_Info(unsigned int Preset); void Load(const char *NavalVehicles, const char *NavalCreationPresets,GameObject *script,const char *SupportVehicles = 0); void Clear(); - static int Purchase_Hook(BaseControllerClass *base, GameObject *purchaser, unsigned int cost, unsigned int preset,const char *data); + static PurchaseStatus Purchase_Hook(BaseControllerClass *base, GameObject *purchaser, unsigned int cost, unsigned int preset,const char *data); static void Object_Hook(void *,GameObject *obj); }; diff -urN sourceold/scripts/sh_factory.cpp source/scripts/sh_factory.cpp --- sourceold/scripts/sh_factory.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/sh_factory.cpp 2024-03-21 19:56:19.037800600 -0500 @@ -51,11 +51,11 @@ monitor_handle = 0; } - int PurchaseHook(BaseControllerClass* base, GameObject* purchaser, unsigned int cost, unsigned int preset) + PurchaseStatus PurchaseHook(BaseControllerClass* base, GameObject* purchaser, unsigned int cost, unsigned int preset) { - if (preset != preset_id || base->Get_Player_Type() != Get_Player_Type(purchaser)) return -1; // not ours, process normally + if (preset != preset_id || base->Get_Player_Type() != Get_Player_Type(purchaser)) return PurchaseStatus_Allow; // not ours, process normally - return -3; // process normally, but prevent creation + return PurchaseStatus_AllowNoSpawn; // process normally, but prevent creation } void PurchaseMonitor(BaseControllerClass* base, GameObject* purchaser, unsigned int cost, unsigned int preset, unsigned int purchase_status) @@ -85,7 +85,7 @@ Commands->Send_Custom_Event(owner, cinematic, CINEMATIC_START, 0, 0); } - static int PurchaseHook(BaseControllerClass* base, GameObject* purchaser, unsigned int cost, unsigned int preset, const char* instance) + static PurchaseStatus PurchaseHook(BaseControllerClass* base, GameObject* purchaser, unsigned int cost, unsigned int preset, const char* instance) { return ((SH_CinematicVehicleFactoryBypass*)instance)->PurchaseHook(base, purchaser, cost, preset); } diff -urN sourceold/scripts/unstoppable.cpp source/scripts/unstoppable.cpp --- sourceold/scripts/unstoppable.cpp 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/unstoppable.cpp 2024-03-21 19:56:19.053425000 -0500 @@ -1474,4 +1474,125 @@ ScriptRegistrant UP_Sound_Controller_3D_Registrant("UP_Sound_Controller_3D", "SoundDef:string,StartCustomType=12300:int,StopCustomType=12301:int"); -/******************************************************************************************************/ \ No newline at end of file +/******************************************************************************************************/ + +void UP_Teleport_Killer_On_Death::Created(GameObject* obj) +{ + TeleportObj = Get_Int_Parameter("TeleportObj"); +} + +void UP_Teleport_Killer_On_Death::Killed(GameObject* obj, GameObject* killer) +{ + if (!killer) return; + + if (GameObject* target = Commands->Find_Object(TeleportObj)) + { + if (!Find_Script_On_Object(target, "UP_Teleport_Killer_Immunity")) + { + Commands->Set_Position(killer, Commands->Get_Position(target)); + } + } +} + +ScriptRegistrant UP_Teleport_Killer_On_Death_Registrant("UP_Teleport_Killer_On_Death", "TeleportObj:int"); + +/******************************************************************************************************/ + +void UP_Teleport_Killer_Immunity::Created(GameObject* obj) +{ + Expire = Get_Float_Parameter("Expire"); + + if (Expire > WWMATH_EPSILON) + { + Commands->Start_Timer(obj, this, Expire, 123); + } +} + +void UP_Teleport_Killer_Immunity::Timer_Expired(GameObject* obj, int number) +{ + if (number == 123) + { + Destroy_Script(); + } +} + +ScriptRegistrant UP_Teleport_Killer_Immunity_Registrant("UP_Teleport_Killer_Immunity", "Expire=0:float"); + +/******************************************************************************************************/ + +void UP_Teleport_On_Zone_Kill::Created(GameObject* obj) +{ + TeleportObj = Get_Int_Parameter("TeleportObj"); +} + +void UP_Teleport_On_Zone_Kill::Entered(GameObject* obj, GameObject* enterer) +{ + Attach_Script_V(enterer, "UP_Teleport_On_Death", "%d", TeleportObj); +} + +void UP_Teleport_On_Zone_Kill::Exited(GameObject* obj, GameObject* exiter) +{ + if (ScriptImpClass* Script = Find_Script_On_Object(exiter, "UP_Teleport_On_Death")) + { + Script->Destroy_Script(); + } +} + +ScriptRegistrant UP_Teleport_On_Zone_Kill_Registrant("UP_Teleport_On_Zone_Kill", "TeleportObj:int"); + +/******************************************************************************************************/ + +void UP_Teleport_Killer_Immunity_Zone::Created(GameObject* obj) +{ + Expire = Get_Float_Parameter("Expire"); +} + +void UP_Teleport_Killer_Immunity_Zone::Entered(GameObject* obj, GameObject* enterer) +{ + Attach_Script_V(enterer, "UP_Teleport_Killer_Immunity", "%f", Expire); +} + +void UP_Teleport_Killer_Immunity_Zone::Exited(GameObject* obj, GameObject* exiter) +{ + if (ScriptImpClass* Script = Find_Script_On_Object(exiter, "UP_Teleport_Killer_Immunity")) + { + Script->Destroy_Script(); + } +} + +ScriptRegistrant UP_Teleport_Killer_Immunity_Zone_Registrant("UP_Teleport_Killer_Immunity_Zone", "Expire=0:float"); + +/******************************************************************************************************/ + +void UP_Gravity_Zone::Created(GameObject* obj) +{ + Multiplier = Get_Float_Parameter("Multiplier"); +} + +void UP_Gravity_Zone::Entered(GameObject* obj, GameObject* enterer) +{ + Set_Gravity_Multiplier(enterer, Multiplier); +} + +void UP_Gravity_Zone::Exited(GameObject* obj, GameObject* exiter) +{ + Set_Gravity_Multiplier(exiter, 1.0f); +} + +ScriptRegistrant UP_Gravity_Zone_Registrant("UP_Gravity_Zone", "Multiplier=0.5:float"); + +/******************************************************************************************************/ + +void UP_No_Targeting_Zone::Entered(GameObject* obj, GameObject* enterer) +{ + Enable_Global_Targeting_Player(enterer, false); +} + +void UP_No_Targeting_Zone::Exited(GameObject* obj, GameObject* exiter) +{ + Enable_Global_Targeting_Player(exiter, true); +} + +ScriptRegistrant UP_No_Targeting_Zone_Registrant("UP_No_Targeting_Zone", ""); + +/******************************************************************************************************/ diff -urN sourceold/scripts/unstoppable.h source/scripts/unstoppable.h --- sourceold/scripts/unstoppable.h 2024-03-08 20:25:22.000000000 -0600 +++ source/scripts/unstoppable.h 2024-03-21 19:56:19.053425000 -0500 @@ -977,4 +977,121 @@ int SoundID; int StartCustomType; int StopCustomType; +}; + +/*! + * \brief Teleport Killer on Death + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Teleports the player who killed this object to the specified object. + * + * \param TeleportObj + * ID of the object to teleport to. + */ +class UP_Teleport_Killer_On_Death : public ScriptImpClass +{ +public: + void Created(GameObject* obj); + void Killed(GameObject* obj, GameObject* killer); + +private: + int TeleportObj; +}; + +/*! + * \brief Immunity for Teleport Killer on Death + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * This is a flag that hints \b UP_Teleport_Killer_On_Death to not teleport the killer. + * + * \param Expire + * Duration in seconds of this immunity. 0 means infinite immunity. + */ +class UP_Teleport_Killer_Immunity : public ScriptImpClass +{ +public: + void Created(GameObject* obj); + void Timer_Expired(GameObject* obj, int number); + +private: + float Expire; +}; + +/*! + * \brief Teleport on Kill inside Zone + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Teleports the killer to specified object when killer kills someone who's inside this zone. + * + * \param TeleportObj + * ID of the object to teleport to. + */ +class UP_Teleport_On_Zone_Kill : public ScriptImpClass +{ +public: + void Created(GameObject* obj); + void Entered(GameObject* obj, GameObject* enterer); + void Exited(GameObject* obj, GameObject* exiter); + +private: + int TeleportObj; +}; + +/*! + * \brief Teleport on Kill Immunity Zone + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Makes the objects who enter this zone immune to the UP_Teleport_Killer_On_Death script. + * + * \param Expire + * Duration in seconds of this immunity. 0 means infinite immunity. + */ +class UP_Teleport_Killer_Immunity_Zone : public ScriptImpClass +{ +public: + void Created(GameObject* obj); + void Entered(GameObject* obj, GameObject* enterer); + void Exited(GameObject* obj, GameObject* exiter); + +private: + float Expire; +}; + +/*! + * \brief Gravity Zone + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Changes the gravity multiplier of objects in the zone. + * + * \param Multiplier + * The gravity multiplier to set. + */ +class UP_Gravity_Zone : public ScriptImpClass +{ +public: + void Created(GameObject* obj); + void Entered(GameObject* obj, GameObject* enterer); + void Exited(GameObject* obj, GameObject* exiter); + +private: + float Multiplier; +}; + +/*! + * \brief No Targeting Zone + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Disables the global targeting of players in the zone. (Except for pokeable objects and buildings) + */ +class UP_No_Targeting_Zone : public ScriptImpClass +{ +public: + void Entered(GameObject* obj, GameObject* enterer); + void Exited(GameObject* obj, GameObject* exiter); }; \ No newline at end of file