re3-wiiu/src/control/Script.h

595 lines
14 KiB
C
Raw Normal View History

2019-06-12 13:46:02 +02:00
#pragma once
2019-07-07 18:00:02 +02:00
#include "common.h"
2020-12-20 15:12:34 +01:00
#include "Ped.h"
2020-01-01 00:35:54 +01:00
#include "PedType.h"
2019-07-27 20:28:18 +02:00
#include "Text.h"
2019-06-15 01:34:19 +02:00
#include "Sprite2d.h"
class CEntity;
class CBuilding;
class CVehicle;
class CPed;
class CObject;
2019-10-27 10:51:09 +01:00
class CPlayerInfo;
2019-06-15 01:34:19 +02:00
2020-02-23 11:12:44 +01:00
class CRunningScript;
extern int32 ScriptParams[32];
void FlushLog();
#define script_assert(_Expression) FlushLog(); assert(_Expression);
#define PICKUP_PLACEMENT_OFFSET 0.5f
#define PED_FIND_Z_OFFSET 5.0f
#define SPHERE_MARKER_R 0
#define SPHERE_MARKER_G 128
#define SPHERE_MARKER_B 255
#define SPHERE_MARKER_A 128
#define SPHERE_MARKER_PULSE_PERIOD 2048
#define SPHERE_MARKER_PULSE_FRACTION 0.1f
#ifdef USE_PRECISE_MEASUREMENT_CONVERTION
#define METERS_IN_FOOT 0.3048f
#define FEET_IN_METER 3.28084f
#else
#define METERS_IN_FOOT 0.3f
#define FEET_IN_METER 3.33f
#endif
2020-02-16 10:44:33 +01:00
#define KEY_LENGTH_IN_SCRIPT 8
2020-12-20 15:07:58 +01:00
#if GTA_VERSION <= GTA_PS2_160
#define GTA_SCRIPT_COLLECTIVE
#endif
2020-04-09 05:20:44 +02:00
struct intro_script_rectangle
2019-06-15 01:34:19 +02:00
{
2020-04-06 01:01:03 +02:00
bool m_bIsUsed;
2019-07-07 19:57:00 +02:00
bool m_bBeforeFade;
2019-07-07 18:00:02 +02:00
int16 m_nTextureId;
2019-06-15 01:34:19 +02:00
CRect m_sRect;
CRGBA m_sColor;
2020-04-09 05:20:44 +02:00
intro_script_rectangle() { }
~intro_script_rectangle() { }
2019-06-15 01:34:19 +02:00
};
VALIDATE_SIZE(intro_script_rectangle, 0x18);
2019-07-07 18:00:02 +02:00
enum {
SCRIPT_TEXT_MAX_LENGTH = 500
};
2020-04-09 05:20:44 +02:00
struct intro_text_line
2019-06-15 01:34:19 +02:00
{
2019-06-17 00:16:38 +02:00
float m_fScaleX;
float m_fScaleY;
2019-06-15 01:34:19 +02:00
CRGBA m_sColor;
2019-06-17 00:16:38 +02:00
bool m_bJustify;
bool m_bCentered;
bool m_bBackground;
bool m_bBackgroundOnly;
float m_fWrapX;
float m_fCenterSize;
2019-06-15 01:34:19 +02:00
CRGBA m_sBackgroundColor;
2019-06-17 00:16:38 +02:00
bool m_bTextProportional;
2019-07-07 18:00:02 +02:00
bool m_bTextBeforeFade;
2019-06-17 00:16:38 +02:00
bool m_bRightJustify;
2019-06-15 01:34:19 +02:00
int32 m_nFont;
2019-07-07 18:00:02 +02:00
float m_fAtX;
float m_fAtY;
wchar m_Text[SCRIPT_TEXT_MAX_LENGTH];
2019-07-07 19:57:00 +02:00
2020-04-09 05:20:44 +02:00
intro_text_line() { }
~intro_text_line() { }
2020-02-23 00:29:38 +01:00
void Reset()
{
m_fScaleX = 0.48f;
m_fScaleY = 1.12f;
m_sColor = CRGBA(225, 225, 225, 255);
m_bJustify = false;
m_bRightJustify = false;
m_bCentered = false;
m_bBackground = false;
m_bBackgroundOnly = false;
m_fWrapX = 182.0f; /* TODO: scaling as bugfix */
m_fCenterSize = 640.0f; /* --||-- */
m_sBackgroundColor = CRGBA(128, 128, 128, 128);
m_bTextProportional = true;
m_bTextBeforeFade = false;
m_nFont = 2; /* enum? */
m_fAtX = 0.0f;
m_fAtY = 0.0f;
memset(&m_Text, 0, sizeof(m_Text));
}
2019-07-07 18:00:02 +02:00
};
VALIDATE_SIZE(intro_text_line, 0x414);
2019-07-07 18:00:02 +02:00
2020-04-09 05:20:44 +02:00
struct script_sphere_struct
2019-07-07 18:00:02 +02:00
{
bool m_bInUse;
uint16 m_Index;
uint32 m_Id;
CVector m_vecCenter;
float m_fRadius;
2020-04-09 05:20:44 +02:00
script_sphere_struct() { }
2019-07-07 18:00:02 +02:00
};
2020-02-24 19:17:15 +01:00
struct CStoredLine
{
CVector vecInf;
CVector vecSup;
uint32 color1;
uint32 color2;
};
2019-07-04 00:16:24 +02:00
enum {
CLEANUP_UNUSED = 0,
CLEANUP_CAR,
CLEANUP_CHAR,
CLEANUP_OBJECT
};
2021-01-01 11:35:23 +01:00
struct cleanup_entity_struct
2019-07-04 00:16:24 +02:00
{
uint8 type;
int32 id;
};
enum {
MAX_CLEANUP = 50,
MAX_UPSIDEDOWN_CAR_CHECKS = 6,
MAX_STUCK_CAR_CHECKS = 6
};
class CMissionCleanup
{
2021-01-01 11:35:23 +01:00
cleanup_entity_struct m_sEntities[MAX_CLEANUP];
2019-07-20 15:30:11 +02:00
uint8 m_nCount;
2019-07-04 00:16:24 +02:00
public:
CMissionCleanup();
void Init();
2021-01-01 11:35:23 +01:00
cleanup_entity_struct* FindFree();
2019-07-04 00:16:24 +02:00
void AddEntityToList(int32, uint8);
void RemoveEntityFromList(int32, uint8);
void Process();
};
struct CUpsideDownCarCheckEntry
{
int32 m_nVehicleIndex;
uint32 m_nUpsideDownTimer;
};
class CUpsideDownCarCheck
{
CUpsideDownCarCheckEntry m_sCars[MAX_UPSIDEDOWN_CAR_CHECKS];
public:
void Init();
bool IsCarUpsideDown(int32);
void UpdateTimers();
bool AreAnyCarsUpsideDown();
void AddCarToCheck(int32);
void RemoveCarFromCheck(int32);
bool HasCarBeenUpsideDownForAWhile(int32);
2019-07-04 00:16:24 +02:00
};
2020-04-09 05:20:44 +02:00
struct stuck_car_data
2019-07-04 00:16:24 +02:00
{
int32 m_nVehicleIndex;
CVector m_vecPos;
int32 m_nLastCheck;
float m_fRadius;
2019-07-04 00:16:24 +02:00
uint32 m_nStuckTime;
bool m_bStuck;
2020-04-09 05:20:44 +02:00
stuck_car_data() { }
inline void Reset();
2019-07-04 00:16:24 +02:00
};
class CStuckCarCheck
{
2020-04-09 05:20:44 +02:00
stuck_car_data m_sCars[MAX_STUCK_CAR_CHECKS];
2019-07-04 00:16:24 +02:00
public:
void Init();
void Process();
void AddCarToCheck(int32, float, uint32);
void RemoveCarFromCheck(int32);
bool HasCarBeenStuckForAWhile(int32);
2019-07-04 00:16:24 +02:00
};
2019-07-07 18:00:02 +02:00
enum {
2019-07-09 22:38:05 +02:00
ARGUMENT_END = 0,
ARGUMENT_INT32,
2019-07-07 18:00:02 +02:00
ARGUMENT_GLOBALVAR,
ARGUMENT_LOCALVAR,
ARGUMENT_INT8,
ARGUMENT_INT16,
ARGUMENT_FLOAT
};
struct tCollectiveData
{
2020-12-20 15:07:58 +01:00
int32 colIndex;
int32 pedIndex;
2019-07-07 18:00:02 +02:00
};
enum {
USED_OBJECT_NAME_LENGTH = 24
};
struct tUsedObject
{
char name[USED_OBJECT_NAME_LENGTH];
int32 index;
};
struct tBuildingSwap
{
CBuilding* m_pBuilding;
int32 m_nNewModel;
int32 m_nOldModel;
};
enum {
VAR_LOCAL = 1,
VAR_GLOBAL = 2,
};
enum {
SIZE_MAIN_SCRIPT = 128 * 1024,
SIZE_MISSION_SCRIPT = 32 * 1024,
SIZE_SCRIPT_SPACE = SIZE_MAIN_SCRIPT + SIZE_MISSION_SCRIPT
};
enum {
MAX_NUM_SCRIPTS = 128,
MAX_NUM_CONTACTS = 16,
MAX_NUM_INTRO_TEXT_LINES = 2,
MAX_NUM_INTRO_RECTANGLES = 16,
MAX_NUM_SCRIPT_SRPITES = 16,
MAX_NUM_SCRIPT_SPHERES = 16,
MAX_NUM_COLLECTIVES = 32,
MAX_NUM_USED_OBJECTS = 200,
MAX_NUM_MISSION_SCRIPTS = 120,
MAX_NUM_BUILDING_SWAPS = 25,
2020-02-24 19:17:15 +01:00
MAX_NUM_INVISIBILITY_SETTINGS = 20,
MAX_NUM_STORED_LINES = 1024
2019-07-07 18:00:02 +02:00
};
2019-06-12 13:46:02 +02:00
class CTheScripts
{
2020-04-17 07:54:14 +02:00
static uint8 ScriptSpace[SIZE_SCRIPT_SPACE];
static CRunningScript ScriptsArray[MAX_NUM_SCRIPTS];
static int32 BaseBriefIdForContact[MAX_NUM_CONTACTS];
static int32 OnAMissionForContactFlag[MAX_NUM_CONTACTS];
static intro_text_line IntroTextLines[MAX_NUM_INTRO_TEXT_LINES];
static intro_script_rectangle IntroRectangles[MAX_NUM_INTRO_RECTANGLES];
static CSprite2d ScriptSprites[MAX_NUM_SCRIPT_SRPITES];
static script_sphere_struct ScriptSphereArray[MAX_NUM_SCRIPT_SPHERES];
static tCollectiveData CollectiveArray[MAX_NUM_COLLECTIVES];
static tUsedObject UsedObjectArray[MAX_NUM_USED_OBJECTS];
static int32 MultiScriptArray[MAX_NUM_MISSION_SCRIPTS];
static tBuildingSwap BuildingSwapArray[MAX_NUM_BUILDING_SWAPS];
static CEntity* InvisibilitySettingArray[MAX_NUM_INVISIBILITY_SETTINGS];
static CStoredLine aStoredLines[MAX_NUM_STORED_LINES];
static bool DbgFlag;
static uint32 OnAMissionFlag;
static CMissionCleanup MissionCleanup;
static CStuckCarCheck StuckCars;
static CUpsideDownCarCheck UpsideDownCars;
static int32 StoreVehicleIndex;
static bool StoreVehicleWasRandom;
static CRunningScript *pIdleScripts;
static CRunningScript *pActiveScripts;
2020-12-20 15:07:58 +01:00
static int32 NextFreeCollectiveIndex;
2020-04-17 07:54:14 +02:00
static int32 LastRandomPedId;
static uint16 NumberOfUsedObjects;
static bool bAlreadyRunningAMissionScript;
static bool bUsingAMultiScriptFile;
static uint16 NumberOfMissionScripts;
static uint32 LargestMissionScriptSize;
static uint32 MainScriptSize;
static uint8 FailCurrentMission;
static uint8 CountdownToMakePlayerUnsafe;
static uint8 DelayMakingPlayerUnsafeThisTime;
static uint16 NumScriptDebugLines;
static uint16 NumberOfIntroRectanglesThisFrame;
static uint16 NumberOfIntroTextLinesThisFrame;
static uint8 UseTextCommands;
static uint16 CommandsExecuted;
static uint16 ScriptsUpdated;
2020-02-23 11:12:44 +01:00
public:
2019-07-07 18:00:02 +02:00
static void Init();
2019-07-07 19:57:00 +02:00
static void Process();
2020-02-23 11:12:44 +01:00
2019-07-07 19:57:00 +02:00
static CRunningScript* StartTestScript();
static bool IsPlayerOnAMission();
2020-02-23 11:12:44 +01:00
static void ClearSpaceForMissionEntity(const CVector&, CEntity*);
2020-02-23 11:30:37 +01:00
2020-02-23 11:12:44 +01:00
static void UndoBuildingSwaps();
static void UndoEntityInvisibilitySettings();
2020-02-23 11:12:44 +01:00
2020-02-24 19:17:15 +01:00
static void ScriptDebugLine3D(float x1, float y1, float z1, float x2, float y2, float z2, uint32 col, uint32 col2);
2020-02-23 11:30:37 +01:00
static void RenderTheScriptDebugLines();
static void SaveAllScripts(uint8*, uint32*);
static void LoadAllScripts(uint8*, uint32);
2020-02-23 11:12:44 +01:00
static bool IsDebugOn() { return DbgFlag; };
static void InvertDebugFlag() { DbgFlag = !DbgFlag; }
2020-03-01 15:42:47 +01:00
static int32* GetPointerToScriptVariable(int32 offset) { assert(offset >= 8 && offset < CTheScripts::GetSizeOfVariableSpace()); return (int32*)&ScriptSpace[offset]; }
2020-02-23 11:12:44 +01:00
static void ResetCountdownToMakePlayerUnsafe() { CountdownToMakePlayerUnsafe = 0; }
static bool IsCountdownToMakePlayerUnsafeOn() { return CountdownToMakePlayerUnsafe != 0; }
2020-03-01 15:42:47 +01:00
static int32 Read4BytesFromScript(uint32* pIp) {
int32 retval = ScriptSpace[*pIp + 3] << 24 | ScriptSpace[*pIp + 2] << 16 | ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
*pIp += 4;
return retval;
}
static int16 Read2BytesFromScript(uint32* pIp) {
int16 retval = ScriptSpace[*pIp + 1] << 8 | ScriptSpace[*pIp];
*pIp += 2;
return retval;
}
static int8 Read1ByteFromScript(uint32* pIp) {
int8 retval = ScriptSpace[*pIp];
*pIp += 1;
return retval;
}
static float ReadFloatFromScript(uint32* pIp) {
return Read2BytesFromScript(pIp) / 16.0f;
}
static void ReadTextLabelFromScript(uint32* pIp, char* buf) {
strncpy(buf, (const char*)&CTheScripts::ScriptSpace[*pIp], KEY_LENGTH_IN_SCRIPT);
}
static wchar* GetTextByKeyFromScript(uint32* pIp) {
wchar* text = TheText.Get((const char*)&CTheScripts::ScriptSpace[*pIp]);
*pIp += KEY_LENGTH_IN_SCRIPT;
return text;
}
static int32 GetSizeOfVariableSpace()
{
uint32 tmp = 3;
return Read4BytesFromScript(&tmp);
}
2020-02-23 11:12:44 +01:00
private:
static CRunningScript* StartNewScript(uint32);
static void CleanUpThisVehicle(CVehicle*);
static void CleanUpThisPed(CPed*);
static void CleanUpThisObject(CObject*);
2019-10-27 10:51:09 +01:00
static bool IsPedStopped(CPed*);
static bool IsPlayerStopped(CPlayerInfo*);
static bool IsVehicleStopped(CVehicle*);
2019-07-07 18:00:02 +02:00
2020-06-21 12:46:23 +02:00
static void PrintListSizes();
2019-07-07 18:00:02 +02:00
static void ReadObjectNamesFromScript();
static void UpdateObjectIndices();
static void ReadMultiScriptFileOffsetsFromScript();
2019-07-07 19:57:00 +02:00
static void DrawScriptSpheres();
2019-07-09 22:38:05 +02:00
static void HighlightImportantArea(uint32, float, float, float, float, float);
2020-02-23 00:29:38 +01:00
static void HighlightImportantAngledArea(uint32, float, float, float, float, float, float, float, float, float);
2019-07-09 22:38:05 +02:00
static void DrawDebugSquare(float, float, float, float);
2020-02-23 00:29:38 +01:00
static void DrawDebugAngledSquare(float, float, float, float, float, float, float, float);
2019-07-09 22:38:05 +02:00
static void DrawDebugCube(float, float, float, float, float, float);
2020-02-23 00:29:38 +01:00
static void DrawDebugAngledCube(float, float, float, float, float, float, float, float, float, float);
2020-02-23 11:30:37 +01:00
2020-01-03 17:48:13 +01:00
static void AddToInvisibilitySwapArray(CEntity*, bool);
2020-02-15 12:53:42 +01:00
static void AddToBuildingSwapArray(CBuilding*, int32, int32);
static int32 GetActualScriptSphereIndex(int32 index);
static int32 AddScriptSphere(int32 id, CVector pos, float radius);
static int32 GetNewUniqueScriptSphereIndex(int32 index);
static void RemoveScriptSphere(int32 index);
2019-07-07 18:00:02 +02:00
2020-12-20 15:07:58 +01:00
#ifdef GTA_SCRIPT_COLLECTIVE
static void AdvanceCollectiveIndex()
{
if (NextFreeCollectiveIndex == INT32_MAX)
NextFreeCollectiveIndex = 0;
else
NextFreeCollectiveIndex++;
}
static int AddPedsInVehicleToCollective(int);
static int AddPedsInAreaToCollective(float, float, float, float);
static int FindFreeSlotInCollectiveArray();
static void SetObjectiveForAllPedsInCollective(int, eObjective, int16, int16);
static void SetObjectiveForAllPedsInCollective(int, eObjective, CVector, float);
static void SetObjectiveForAllPedsInCollective(int, eObjective, CVector);
static void SetObjectiveForAllPedsInCollective(int, eObjective, void*);
static void SetObjectiveForAllPedsInCollective(int, eObjective);
#endif
2020-02-23 11:12:44 +01:00
friend class CRunningScript;
friend class CHud;
friend void CMissionCleanup::Process();
2020-12-08 01:27:35 +01:00
#ifdef MISSION_REPLAY
2020-05-26 23:25:12 +02:00
friend void RetryMission(int, int);
#endif
2020-11-16 00:41:03 +01:00
#ifdef MISSION_SWITCHER
public:
static void SwitchToMission(int32 mission);
#endif
2020-02-23 11:12:44 +01:00
};
enum {
2020-06-27 23:01:51 +02:00
MAX_STACK_DEPTH = 6, // 4 PS2
2020-02-23 11:12:44 +01:00
NUM_LOCAL_VARS = 16,
NUM_TIMERS = 2
};
class CRunningScript
{
enum {
ANDOR_NONE = 0,
ANDS_1 = 1,
ANDS_2,
ANDS_3,
ANDS_4,
ANDS_5,
ANDS_6,
ANDS_7,
ANDS_8,
ORS_1 = 21,
ORS_2,
ORS_3,
ORS_4,
ORS_5,
ORS_6,
ORS_7,
ORS_8
};
CRunningScript* next;
CRunningScript* prev;
char m_abScriptName[8];
uint32 m_nIp;
uint32 m_anStack[MAX_STACK_DEPTH];
uint16 m_nStackPointer;
int32 m_anLocalVariables[NUM_LOCAL_VARS + NUM_TIMERS];
bool m_bCondResult;
bool m_bIsMissionScript;
bool m_bSkipWakeTime;
uint32 m_nWakeTime;
uint16 m_nAndOrState;
bool m_bNotFlag;
bool m_bDeatharrestEnabled;
bool m_bDeatharrestExecuted;
bool m_bMissionFlag;
public:
void SetIP(uint32 ip) { m_nIp = ip; }
CRunningScript* GetNext() const { return next; }
2020-05-03 00:42:46 +02:00
void Save(uint8*& buf);
void Load(uint8*& buf);
2020-02-23 11:12:44 +01:00
void UpdateTimers(float timeStep) {
m_anLocalVariables[NUM_LOCAL_VARS] += timeStep;
m_anLocalVariables[NUM_LOCAL_VARS + 1] += timeStep;
}
void Init();
void Process();
void RemoveScriptFromList(CRunningScript**);
void AddScriptToList(CRunningScript**);
2020-05-03 00:42:46 +02:00
static const uint32 nSaveStructSize;
2020-02-23 11:12:44 +01:00
private:
void CollectParameters(uint32*, int16);
int32 CollectNextParameterWithoutIncreasingPC(uint32);
int32* GetPointerToScriptVariable(uint32*, int16);
void StoreParameters(uint32*, int16);
int8 ProcessOneCommand();
void DoDeatharrestCheck();
void UpdateCompareFlag(bool);
int16 GetPadState(uint16, uint16);
int8 ProcessCommands0To99(int32);
int8 ProcessCommands100To199(int32);
int8 ProcessCommands200To299(int32);
int8 ProcessCommands300To399(int32);
int8 ProcessCommands400To499(int32);
int8 ProcessCommands500To599(int32);
int8 ProcessCommands600To699(int32);
int8 ProcessCommands700To799(int32);
int8 ProcessCommands800To899(int32);
int8 ProcessCommands900To999(int32);
int8 ProcessCommands1000To1099(int32);
#ifndef GTA_PS2
int8 ProcessCommands1100To1199(int32);
#endif
void LocatePlayerCommand(int32, uint32*);
void LocatePlayerCharCommand(int32, uint32*);
void LocatePlayerCarCommand(int32, uint32*);
void LocateCharCommand(int32, uint32*);
void LocateCharCharCommand(int32, uint32*);
void LocateCharCarCommand(int32, uint32*);
void LocateCharObjectCommand(int32, uint32*);
void LocateCarCommand(int32, uint32*);
void LocateSniperBulletCommand(int32, uint32*);
void PlayerInAreaCheckCommand(int32, uint32*);
void PlayerInAngledAreaCheckCommand(int32, uint32*);
void CharInAreaCheckCommand(int32, uint32*);
void CarInAreaCheckCommand(int32, uint32*);
2020-12-20 15:07:58 +01:00
#ifdef GTA_SCRIPT_COLLECTIVE
void LocateCollectiveCommand(int32, uint32*);
void LocateCollectiveCharCommand(int32, uint32*);
void LocateCollectiveCarCommand(int32, uint32*);
void LocateCollectivePlayerCommand(int32, uint32*);
void CollectiveInAreaCheckCommand(int32, uint32*);
#endif
2020-05-26 23:25:12 +02:00
#ifdef MISSION_REPLAY
bool CanAllowMissionReplay();
#endif
2020-06-21 12:46:23 +02:00
#ifdef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT
int CollectParameterForDebug(char* buf, bool& var);
void GetStoredParameterForDebug(char* buf);
#endif
2020-02-23 11:12:44 +01:00
float LimitAngleOnCircle(float angle) { return angle < 0.0f ? angle + 360.0f : angle; }
bool ThisIsAValidRandomPed(uint32 pedtype) {
switch (pedtype) {
case PEDTYPE_CIVMALE:
case PEDTYPE_CIVFEMALE:
case PEDTYPE_GANG1:
case PEDTYPE_GANG2:
case PEDTYPE_GANG3:
case PEDTYPE_GANG4:
case PEDTYPE_GANG5:
case PEDTYPE_GANG6:
case PEDTYPE_GANG7:
case PEDTYPE_GANG8:
case PEDTYPE_GANG9:
case PEDTYPE_CRIMINAL:
case PEDTYPE_PROSTITUTE:
return true;
default:
return false;
}
}
2020-11-16 00:41:03 +01:00
friend class CTheScripts;
2019-06-12 13:46:02 +02:00
};
2020-05-26 23:25:12 +02:00
#ifdef MISSION_REPLAY
extern int AllowMissionReplay;
extern uint32 WaitForMissionActivate;
extern uint32 WaitForSave;
extern uint32 MissionStartTime;
extern int missionRetryScriptIndex;
extern bool doingMissionRetry;
uint32 AddExtraDeathDelay();
void RetryMission(int, int);
#endif
2020-05-28 11:46:51 +02:00
#ifdef USE_DEBUG_SCRIPT_LOADER
extern int scriptToLoad;
#endif