1 /*
2 Copyright (C) 2009-2021 Parallel Realities
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18 */
19 
20 #include "../headers.h"
21 
22 #include "../entity.h"
23 #include "../event/script.h"
24 #include "../hud.h"
25 #include "../inventory.h"
26 #include "../system/error.h"
27 #include "objective.h"
28 #include "trigger.h"
29 
30 static Trigger trigger[MAX_TRIGGERS];
31 static Type type[] = {
32 					{UPDATE_OBJECTIVE, "UPDATE_OBJECTIVE"},
33 					{ACTIVATE_ENTITY, "ACTIVATE_ENTITY"},
34 					{DEACTIVATE_ENTITY, "DEACTIVATE_ENTITY"},
35 					{RUN_SCRIPT, "RUN_SCRIPT"},
36 					{UPDATE_TRIGGER, "UPDATE_TRIGGER"},
37 					{KILL_ENTITY, "KILL_ENTITY"},
38 					{REMOVE_INVENTORY_ITEM, "REMOVE_INVENTORY_ITEM"},
39 					{UPDATE_EXIT, "UPDATE_EXIT"}
40 					};
41 static int length = sizeof(type) / sizeof(Type);
42 
43 static void addTrigger(char *, int, int, int, char *);
44 
freeTriggers()45 void freeTriggers()
46 {
47 	/* Clear the list */
48 
49 	memset(trigger, 0, sizeof(Trigger) * MAX_TRIGGERS);
50 }
51 
addTriggerFromResource(char * key[],char * value[])52 void addTriggerFromResource(char *key[], char *value[])
53 {
54 	int i, triggerName, count, targetType, targetName, total;
55 
56 	total = triggerName = count = targetType = targetName = -1;
57 
58 	for (i=0;i<MAX_PROPS_FILES;i++)
59 	{
60 		if (strcmpignorecase("TRIGGER_NAME", key[i]) == 0)
61 		{
62 			triggerName = i;
63 		}
64 
65 		else if (strcmpignorecase("TRIGGER_COUNT", key[i]) == 0)
66 		{
67 			count = i;
68 		}
69 
70 		else if (strcmpignorecase("TRIGGER_TOTAL", key[i]) == 0)
71 		{
72 			total = i;
73 		}
74 
75 		else if (strcmpignorecase("TRIGGER_TYPE", key[i]) == 0)
76 		{
77 			targetType = i;
78 		}
79 
80 		else if (strcmpignorecase("TRIGGER_TARGET", key[i]) == 0)
81 		{
82 			targetName = i;
83 		}
84 	}
85 
86 	if (total == -1 && count != -1)
87 	{
88 		total = count;
89 
90 		count = 0;
91 	}
92 
93 	if (triggerName == -1 || count == -1 || targetType == -1 || targetName == -1 || total == -1)
94 	{
95 		showErrorAndExit("Trigger is missing resources");
96 	}
97 
98 	addTrigger(value[triggerName], atoi(value[count]), atoi(value[total]), getTriggerTypeByName(value[targetType]), value[targetName]);
99 }
100 
addTrigger(char * triggerName,int count,int total,int targetType,char * targetName)101 static void addTrigger(char *triggerName, int count, int total, int targetType, char *targetName)
102 {
103 	int i;
104 
105 	for (i=0;i<MAX_TRIGGERS;i++)
106 	{
107 		if (trigger[i].inUse == FALSE)
108 		{
109 			trigger[i].inUse = TRUE;
110 
111 			trigger[i].count = count;
112 			trigger[i].total = total;
113 			trigger[i].targetType = targetType;
114 
115 			STRNCPY(trigger[i].triggerName, triggerName, sizeof(trigger[i].triggerName));
116 			STRNCPY(trigger[i].targetName, targetName, sizeof(trigger[i].targetName));
117 
118 			return;
119 		}
120 	}
121 
122 	showErrorAndExit("No free slots to add Trigger \"%s\"", triggerName);
123 }
124 
fireTrigger(char * name)125 void fireTrigger(char *name)
126 {
127 	int i;
128 	char message[MAX_MESSAGE_LENGTH];
129 
130 	if (strlen(name) == 0)
131 	{
132 		return;
133 	}
134 
135 	for (i=0;i<MAX_TRIGGERS;i++)
136 	{
137 		if (trigger[i].inUse == TRUE && strcmpignorecase(trigger[i].triggerName, name) == 0)
138 		{
139 			trigger[i].count++;
140 
141 			if (trigger[i].targetType == UPDATE_OBJECTIVE)
142 			{
143 				SNPRINTF(message, MAX_MESSAGE_LENGTH, "%s (%d / %d)", _(trigger[i].targetName), trigger[i].count, trigger[i].total);
144 
145 				freeMessageQueue();
146 
147 				setInfoBoxMessage(60, 255, 255, 255, message);
148 			}
149 
150 			if (trigger[i].count == trigger[i].total)
151 			{
152 				switch (trigger[i].targetType)
153 				{
154 					case UPDATE_OBJECTIVE:
155 						updateObjective(trigger[i].targetName);
156 					break;
157 
158 					case ACTIVATE_ENTITY:
159 						activateEntitiesWithRequiredName(trigger[i].targetName, TRUE);
160 					break;
161 
162 					case DEACTIVATE_ENTITY:
163 						activateEntitiesWithRequiredName(trigger[i].targetName, FALSE);
164 					break;
165 
166 					case RUN_SCRIPT:
167 						runScript(trigger[i].targetName);
168 					break;
169 
170 					case KILL_ENTITY:
171 						killEntity(trigger[i].targetName);
172 					break;
173 
174 					case REMOVE_INVENTORY_ITEM:
175 						removeInventoryItemByObjectiveName(trigger[i].targetName);
176 					break;
177 
178 					case UPDATE_TRIGGER:
179 						fireTrigger(trigger[i].targetName);
180 					break;
181 
182 					default:
183 
184 					break;
185 				}
186 
187 				trigger[i].inUse = FALSE;
188 			}
189 		}
190 	}
191 }
192 
removeTrigger(char * name)193 void removeTrigger(char *name)
194 {
195 	int i;
196 
197 	for (i=0;i<MAX_TRIGGERS;i++)
198 	{
199 		if (trigger[i].inUse == TRUE && strcmpignorecase(trigger[i].triggerName, name) == 0)
200 		{
201 			trigger[i].inUse = FALSE;
202 
203 			break;
204 		}
205 	}
206 }
207 
updateTrigger(char * name,int value)208 void updateTrigger(char *name, int value)
209 {
210 	int i;
211 
212 	if (strlen(name) == 0)
213 	{
214 		return;
215 	}
216 
217 	for (i=0;i<MAX_TRIGGERS;i++)
218 	{
219 		if (trigger[i].inUse == TRUE && strcmpignorecase(trigger[i].triggerName, name) == 0)
220 		{
221 			printf("Modifying trigger value from %d to %d\n", trigger[i].count, (trigger[i].count - value));
222 
223 			trigger[i].count -= value;
224 		}
225 	}
226 }
227 
writeTriggersToFile(FILE * fp)228 void writeTriggersToFile(FILE *fp)
229 {
230 	int i;
231 
232 	for (i=0;i<MAX_TRIGGERS;i++)
233 	{
234 		if (trigger[i].inUse == TRUE)
235 		{
236 			fprintf(fp, "{\n");
237 			fprintf(fp, "TYPE TRIGGER\n");
238 			fprintf(fp, "TRIGGER_NAME %s\n", trigger[i].triggerName);
239 			fprintf(fp, "TRIGGER_COUNT %d\n", trigger[i].count);
240 			fprintf(fp, "TRIGGER_TOTAL %d\n", trigger[i].total);
241 			fprintf(fp, "TRIGGER_TYPE %s\n", getTriggerTypeByID(trigger[i].targetType));
242 			fprintf(fp, "TRIGGER_TARGET %s\n", trigger[i].targetName);
243 			fprintf(fp, "}\n\n");
244 		}
245 	}
246 }
247 
getTriggerTypeByName(char * name)248 int getTriggerTypeByName(char *name)
249 {
250 	int i;
251 
252 	for (i=0;i<length;i++)
253 	{
254 		if (strcmpignorecase(name, type[i].name) == 0)
255 		{
256 			return type[i].id;
257 		}
258 	}
259 
260 	showErrorAndExit("Unknown Trigger Type %s", name);
261 
262 	return 0;
263 }
264 
getTriggerTypeByID(int id)265 char *getTriggerTypeByID(int id)
266 {
267 	int i;
268 
269 	for (i=0;i<length;i++)
270 	{
271 		if (id == type[i].id)
272 		{
273 			return type[i].name;
274 		}
275 	}
276 
277 	showErrorAndExit("Unknown Trigger ID %d", id);
278 
279 	return 0;
280 }
281