Skip to content

Commit ad63ffc

Browse files
committed
Load custom logics from JSON
1 parent bc8a7c6 commit ad63ffc

File tree

7 files changed

+295
-139
lines changed

7 files changed

+295
-139
lines changed

TheForceEngine/TFE_DarkForces/Actor/animTables.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ namespace TFE_DarkForces
3333
const s32 s_commandoAnimTable[] =
3434
{ 0, 1, 2, 3, 4, 5, 6, -1, -1, -1, -1, -1, 12, -1, -1, -1 };
3535

36+
// For custom sprites - based on enemies but with all anims used
37+
const s32 s_customAnimTable[] =
38+
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, 12, -1, -1, -1 };
39+
3640
// Internal State.
3741
static const s32* const s_animTables[] =
3842
{

TheForceEngine/TFE_DarkForces/Actor/animTables.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ namespace TFE_DarkForces
3636
extern const s32 s_officerAnimTable[];
3737
extern const s32 s_troopAnimTable[];
3838
extern const s32 s_commandoAnimTable[];
39+
40+
// Custom
41+
extern const s32 s_customAnimTable[];
3942
} // namespace TFE_DarkForces

TheForceEngine/TFE_DarkForces/Actor/enemies.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ namespace TFE_DarkForces
251251
moveMod->collisionFlags |= 1;
252252
}
253253

254-
dispatch->animTable = s_reeyeesAnimTable; //***************************
254+
dispatch->animTable = s_customAnimTable;
255255
actor_setupInitAnimation();
256256

257257
return (Logic*)dispatch;
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
#include <vector>
2+
#include <TFE_Settings/logics.h>
3+
#include <TFE_System/cJSON.h>
4+
#include <TFE_System/system.h>
5+
6+
namespace TFE_Settings
7+
{
8+
///////////////////////////
9+
/// Forward declarations
10+
///////////////////////////
11+
bool tryAssignProperty(cJSON* data, CustomActorLogic& customLogic);
12+
13+
14+
void parseLogicData(char* data, std::vector<CustomActorLogic> &actorLogics)
15+
{
16+
cJSON* root = cJSON_Parse(data);
17+
if (root)
18+
{
19+
cJSON* section = root->child;
20+
if (section && cJSON_IsArray(section) && strcasecmp(section->string, "logics") == 0)
21+
{
22+
cJSON* logic = section->child;
23+
while (logic)
24+
{
25+
cJSON* logicName = logic->child;
26+
27+
// get the logic name
28+
if (logicName && cJSON_IsString(logicName) && strcasecmp(logicName->string, "logicname") == 0)
29+
{
30+
CustomActorLogic customLogic;
31+
customLogic.logicName = logicName->valuestring;
32+
33+
cJSON* logicData = logicName->next;
34+
if (logicData && cJSON_IsObject(logicData))
35+
{
36+
cJSON* dataItem = logicData->child;
37+
38+
// iterate through the data and assign properties
39+
while (dataItem)
40+
{
41+
tryAssignProperty(dataItem, customLogic);
42+
dataItem = dataItem->next;
43+
}
44+
}
45+
46+
actorLogics.push_back(customLogic);
47+
}
48+
49+
logic = logic->next;
50+
}
51+
}
52+
}
53+
else
54+
{
55+
const char* error = cJSON_GetErrorPtr();
56+
if (error)
57+
{
58+
TFE_System::logWrite(LOG_ERROR, "LOGICS", "Failed to parse logics.json before\n%s", error);
59+
}
60+
else
61+
{
62+
TFE_System::logWrite(LOG_ERROR, "LOGICS", "Failed to parse logics.json");
63+
}
64+
}
65+
66+
std::vector<CustomActorLogic> test = actorLogics;
67+
}
68+
69+
bool tryAssignProperty(cJSON* data, CustomActorLogic &customLogic)
70+
{
71+
if (!data)
72+
{
73+
return false;
74+
}
75+
76+
if (cJSON_IsBool(data) && strcasecmp(data->string, "hasGravity") == 0)
77+
{
78+
customLogic.hasGravity = cJSON_IsTrue(data);
79+
return true;
80+
}
81+
82+
if (cJSON_IsBool(data) && strcasecmp(data->string, "isFlying") == 0)
83+
{
84+
customLogic.isFlying = cJSON_IsTrue(data);
85+
return true;
86+
}
87+
88+
if (cJSON_IsString(data) && strcasecmp(data->string, "alertSound") == 0)
89+
{
90+
customLogic.alertSound = data->valuestring;
91+
return true;
92+
}
93+
94+
if (cJSON_IsString(data) && strcasecmp(data->string, "painSound") == 0)
95+
{
96+
customLogic.painSound = data->valuestring;
97+
return true;
98+
}
99+
100+
if (cJSON_IsString(data) && strcasecmp(data->string, "dieSound") == 0)
101+
{
102+
customLogic.dieSound = data->valuestring;
103+
return true;
104+
}
105+
106+
if (cJSON_IsString(data) && strcasecmp(data->string, "attack1Sound") == 0)
107+
{
108+
customLogic.attack1Sound = data->valuestring;
109+
return true;
110+
}
111+
112+
if (cJSON_IsString(data) && strcasecmp(data->string, "attack2Sound") == 0)
113+
{
114+
customLogic.attack2Sound = data->valuestring;
115+
return true;
116+
}
117+
118+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "hitPoints") == 0)
119+
{
120+
customLogic.hitPoints = data->valueint;
121+
return true;
122+
}
123+
124+
/**** replace with string lookup ***/
125+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "dropItem") == 0)
126+
{
127+
customLogic.dropItem = data->valueint;
128+
return true;
129+
}
130+
131+
if (cJSON_IsBool(data) && strcasecmp(data->string, "hasMeleeAttack") == 0)
132+
{
133+
customLogic.hasMeleeAttack = cJSON_IsTrue(data);
134+
return true;
135+
}
136+
137+
if (cJSON_IsBool(data) && strcasecmp(data->string, "hasRangedAttack") == 0)
138+
{
139+
customLogic.hasRangedAttack = cJSON_IsTrue(data);
140+
return true;
141+
}
142+
143+
if (cJSON_IsBool(data) && strcasecmp(data->string, "litWithMeleeAttack") == 0)
144+
{
145+
customLogic.litWithMeleeAttack = cJSON_IsTrue(data);
146+
return true;
147+
}
148+
149+
if (cJSON_IsBool(data) && strcasecmp(data->string, "litWithRangedAttack") == 0)
150+
{
151+
customLogic.litWithRangedAttack = cJSON_IsTrue(data);
152+
return true;
153+
}
154+
155+
/**** replace with string lookup ***/
156+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "projectile") == 0)
157+
{
158+
customLogic.projectile = data->valueint;
159+
return true;
160+
}
161+
162+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "rangedAttackDelay") == 0)
163+
{
164+
customLogic.rangedAttackDelay = data->valueint;
165+
return true;
166+
}
167+
168+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "meleeAttackDelay") == 0)
169+
{
170+
customLogic.meleeAttackDelay = data->valueint;
171+
return true;
172+
}
173+
174+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "meleeRange") == 0)
175+
{
176+
customLogic.meleeRange = data->valueint;
177+
return true;
178+
}
179+
180+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "meleeDamage") == 0)
181+
{
182+
customLogic.meleeDamage = data->valueint;
183+
return true;
184+
}
185+
186+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "meleeRate") == 0)
187+
{
188+
customLogic.meleeRate = data->valueint;
189+
return true;
190+
}
191+
192+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "minAttackDist") == 0)
193+
{
194+
customLogic.minAttackDist = data->valueint;
195+
return true;
196+
}
197+
198+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "maxAttackDist") == 0)
199+
{
200+
customLogic.maxAttackDist = data->valueint;
201+
return true;
202+
}
203+
204+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "speed") == 0)
205+
{
206+
customLogic.speed = data->valueint;
207+
return true;
208+
}
209+
210+
if (cJSON_IsNumber(data) && strcasecmp(data->string, "verticalSpeed") == 0)
211+
{
212+
customLogic.verticalSpeed = data->valueint;
213+
return true;
214+
}
215+
216+
return false;
217+
}
218+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
//////////////////////////
3+
// TFE Custom Logics
4+
//////////////////////////
5+
6+
#include <TFE_System/types.h>
7+
8+
struct CustomActorLogic
9+
{
10+
const char* logicName;
11+
bool hasGravity = true;
12+
bool isFlying = false;
13+
14+
const char* alertSound = "";
15+
const char* painSound = "";
16+
const char* attack1Sound = "";
17+
const char* attack2Sound = "";
18+
const char* dieSound = "";
19+
20+
// Defaults are based on what is set by default in the original code
21+
u32 hitPoints = 4;
22+
s32 dropItem = -1;
23+
24+
bool hasMeleeAttack = false;
25+
bool hasRangedAttack = true;
26+
bool litWithMeleeAttack = false;
27+
bool litWithRangedAttack = true;
28+
s32 projectile = 2;
29+
u32 rangedAttackDelay = 291;
30+
u32 meleeAttackDelay = 0;
31+
u32 meleeRange = 0;
32+
u32 meleeDamage = 0;
33+
u32 meleeRate = 230;
34+
u32 minAttackDist = 0;
35+
u32 maxAttackDist = 160;
36+
37+
u32 speed = 4;
38+
u32 verticalSpeed = 10;
39+
};
40+
41+
struct ExternalLogics
42+
{
43+
std::vector<CustomActorLogic> actorLogics;
44+
};
45+
46+
namespace TFE_Settings
47+
{
48+
void parseLogicData(char* data, std::vector<CustomActorLogic> &actorLogics);
49+
}

0 commit comments

Comments
 (0)