1 /*
2  * OpenBOR - http://www.chronocrash.com
3  * -----------------------------------------------------------------------
4  * All rights reserved. See LICENSE in OpenBOR root for license details.
5  *
6  * Copyright (c) 2004 - 2017 OpenBOR Team
7  */
8 
9 // Binding Properties
10 // 2018-03-31
11 // Caskey, Damon V.
12 
13 #include "scriptcommon.h"
14 
15 // Use string property argument to find an
16 // integer property constant and populate
17 // varlist->lval.
mapstrings_bind_property(ScriptVariant ** varlist,int paramCount)18 int mapstrings_bind_property(ScriptVariant **varlist, int paramCount)
19 {
20     #define ARG_MINIMUM     2   // Minimum number of arguments allowed in varlist.
21     #define ARG_PROPERTY    1   // Varlist element carrying which property is requested.
22 
23     char *propname = NULL;  // Placeholder for string property name from varlist.
24     int prop;               // Placeholder for integer constant located by string.
25 
26     static const char *proplist[] =
27     {
28 		"animation_frame",
29 		"animation_id",
30 		"animation_match",
31 		"direction",
32 		"mode_x",
33 		"mode_y",
34 		"mode_z",
35 		"offset_x",
36 		"offset_y",
37 		"offset_z",
38         "override",
39         "sort_id",
40         "tag",
41         "target"
42     };
43 
44     // If the minimum argument count
45     // was not passed, then there is
46     // nothing to map. Return true - we'll
47     // catch the mistake in property access
48     // functions.
49     if(paramCount < ARG_MINIMUM)
50     {
51         return 1;
52     }
53 
54     // See macro - will return 0 on fail.
55     MAPSTRINGS(varlist[ARG_PROPERTY], proplist, _BIND_END,
56                "Property name '%s' is not supported by binding.\n");
57 
58 
59     // If we made it this far everything should be OK.
60     return 1;
61 
62     #undef ARG_MINIMUM
63     #undef ARG_PROPERTY
64 }
65 
66 // Caskey, Damon  V.
67 // 2018-03-31
68 //
69 // Return a binding property. Requires
70 // the handle from binding entity
71 // property and property name to
72 // access.
openbor_get_bind_property(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)73 HRESULT openbor_get_bind_property(ScriptVariant **varlist , ScriptVariant **pretvar, int paramCount)
74 {
75     #define SELF_NAME       "openbor_get_bind_property(void bind, char property)"
76     #define ARG_MINIMUM     2   // Minimum required arguments.
77     #define ARG_HANDLE      0   // Handle (pointer to property structure).
78     #define ARG_PROPERTY    1   // Property to access.
79 
80     s_bind              *handle     = NULL; // Property handle.
81     e_bind_properties	property    = 0;    // Property argument.
82 
83     // Clear pass by reference argument used to send
84     // property data back to calling script.     .
85     ScriptVariant_Clear(*pretvar);
86 
87     // Map string property name to a
88     // matching integer constant.
89     mapstrings_bind_property(varlist, paramCount);
90 
91     // Verify arguments. There should at least
92     // be a pointer for the property handle and an integer
93     // to determine which property constant is accessed.
94     if(paramCount < ARG_MINIMUM
95        || varlist[ARG_HANDLE]->vt != VT_PTR
96        || varlist[ARG_PROPERTY]->vt != VT_INTEGER)
97     {
98         *pretvar = NULL;
99         goto error_local;
100     }
101     else
102     {
103         // Populate local vars for readability.
104         handle      = (s_bind *)varlist[ARG_HANDLE]->ptrVal;
105         property    = (LONG)varlist[ARG_PROPERTY]->lVal;
106     }
107 
108     switch(property)
109     {
110 		case _BIND_ANIMATION_FRAME:
111 
112 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
113 			(*pretvar)->lVal = (LONG)handle->frame;
114 
115 			break;
116 
117 		case _BIND_ANIMATION_ID:
118 
119 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
120 			(*pretvar)->lVal = (LONG)handle->animation;
121 
122 			break;
123 
124 		case _BIND_ANIMATION_MATCH:
125 
126 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
127 			(*pretvar)->lVal = (LONG)handle->match;
128 
129 			break;
130 
131         case _BIND_DIRECTION:
132 
133             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
134             (*pretvar)->lVal = (LONG)handle->direction;
135 
136             break;
137 
138 		case _BIND_MODE_X:
139 
140 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
141 			(*pretvar)->lVal = (LONG)handle->positioning.x;
142 
143 			break;
144 
145 		case _BIND_MODE_Y:
146 
147 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
148 			(*pretvar)->lVal = (LONG)handle->positioning.y;
149 
150 			break;
151 
152 		case _BIND_MODE_Z:
153 
154 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
155 			(*pretvar)->lVal = (LONG)handle->positioning.z;
156 
157 			break;
158 
159         case _BIND_OFFSET_X:
160 
161 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
162 			(*pretvar)->lVal = (LONG)handle->offset.x;
163 
164 			break;
165 
166 		case _BIND_OFFSET_Y:
167 
168 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
169 			(*pretvar)->lVal = (LONG)handle->offset.y;
170 
171 			break;
172 
173 		case _BIND_OFFSET_Z:
174 
175 			ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
176 			(*pretvar)->lVal = (LONG)handle->offset.z;
177 
178 			break;
179 
180         case _BIND_OVERRIDE:
181 
182             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
183             (*pretvar)->lVal = (LONG)handle->overriding;
184 
185             break;
186 
187         case _BIND_SORT_ID:
188 
189             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
190             (*pretvar)->lVal = (LONG)handle->sortid;
191 
192             break;
193 
194         case _BIND_TAG:
195 
196             ScriptVariant_ChangeType(*pretvar, VT_INTEGER);
197             (*pretvar)->lVal = (LONG)handle->tag;
198 
199             break;
200 
201         case _BIND_TARGET:
202 
203             // If there is no entity bound, we just
204             // leave the return var empty.
205             if(handle->ent)
206             {
207                 ScriptVariant_ChangeType(*pretvar, VT_PTR);
208                 (*pretvar)->ptrVal = (entity *)handle->ent;
209             }
210 
211             break;
212 
213         default:
214 
215             printf("Unsupported property.\n");
216             goto error_local;
217 
218             break;
219     }
220 
221     return S_OK;
222 
223     error_local:
224 
225     printf("\nYou must provide a valid pointer and property name: " SELF_NAME "\n");
226     *pretvar = NULL;
227 
228     return E_FAIL;
229 
230     #undef SELF_NAME
231     #undef ARG_MINIMUM
232     #undef ARG_HANDLE
233     #undef ARG_INDEX
234 }
235 
236 // Caskey, Damon  V.
237 // 2018-04-01
238 //
239 // Mutate a binding property. Requires
240 // the handle from binding entity
241 // property, property name to modify,
242 // and the new value.
openbor_set_bind_property(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)243 HRESULT openbor_set_bind_property(ScriptVariant **varlist, ScriptVariant **pretvar, int paramCount)
244 {
245     #define SELF_NAME           "set_bind_property(void bind, char property, mixed value)"
246     #define ARG_MINIMUM         3   // Minimum required arguments.
247     #define ARG_HANDLE          0   // Handle (pointer to property structure).
248     #define ARG_PROPERTY        1   // Property to access.
249     #define ARG_VALUE           2   // New value to apply.
250 
251 	int                     result = S_OK; // Success or error?
252 	s_bind                  *handle = NULL; // Property handle.
253 	e_bind_properties    property = 0;    // Property to access.
254 
255 	// Value carriers to apply on properties after
256 	// taken from argument.
257 	LONG         temp_int;
258 
259 	// Map string property name to a
260 	// matching integer constant.
261 	mapstrings_bind_property(varlist, paramCount);
262 
263 	// Verify incoming arguments. There should at least
264 	// be a pointer for the property handle and an integer
265 	// to determine which property is accessed.
266 	if (paramCount < ARG_MINIMUM
267 		|| varlist[ARG_HANDLE]->vt != VT_PTR
268 		|| varlist[ARG_PROPERTY]->vt != VT_INTEGER)
269 	{
270 		*pretvar = NULL;
271 		goto error_local;
272 	}
273 
274 	// Populate local handle and property vars.
275 	handle = (s_bind *)varlist[ARG_HANDLE]->ptrVal;
276 	property = (LONG)varlist[ARG_PROPERTY]->lVal;
277 
278 	// Which property to modify?
279 	switch (property)
280 	{
281 
282 		case _BIND_ANIMATION_FRAME:
283 
284 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
285 			{
286 				handle->frame = temp_int;
287 			}
288 
289 			break;
290 
291 		case _BIND_ANIMATION_ID:
292 
293 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
294 			{
295 				handle->animation = temp_int;
296 			}
297 
298 			break;
299 
300 		case _BIND_ANIMATION_MATCH:
301 
302 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
303 			{
304 				handle->match = temp_int;
305 			}
306 
307 			break;
308 
309 		case _BIND_DIRECTION:
310 
311 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
312 			{
313 				handle->direction = temp_int;
314 			}
315 
316 			break;
317 
318 		case _BIND_MODE_X:
319 
320 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
321 			{
322 				handle->positioning.x = temp_int;
323 			}
324 
325 			break;
326 
327 		case _BIND_MODE_Y:
328 
329 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
330 			{
331 				handle->positioning.y = temp_int;
332 			}
333 
334 			break;
335 
336 		case _BIND_MODE_Z:
337 
338 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
339 			{
340 				handle->positioning.z = temp_int;
341 			}
342 
343 			break;
344 
345 		case _BIND_OFFSET_X:
346 
347 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
348 			{
349 				handle->offset.x = temp_int;
350 			}
351 
352 			break;
353 
354 		case _BIND_OFFSET_Y:
355 
356 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
357 			{
358 				handle->offset.y = temp_int;
359 			}
360 
361 			break;
362 
363 		case _BIND_OFFSET_Z:
364 
365 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
366 			{
367 				handle->offset.z = temp_int;
368 			}
369 
370 			break;
371 
372 		case _BIND_OVERRIDE:
373 
374 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
375 			{
376 				handle->overriding = temp_int;
377 			}
378 
379 			break;
380 
381 		case _BIND_SORT_ID:
382 
383 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
384 			{
385 				handle->sortid = temp_int;
386 			}
387 
388 			break;
389 
390 		case _BIND_TAG:
391 
392 			if (SUCCEEDED(ScriptVariant_IntegerValue(varlist[ARG_VALUE], &temp_int)))
393 			{
394 				handle->tag = temp_int;
395 			}
396 
397 			break;
398 
399 		case _BIND_TARGET:
400 
401 			handle->ent = (entity *)varlist[ARG_VALUE]->ptrVal;
402 
403 			break;
404 
405 		default:
406 
407 			printf("Unsupported property.\n");
408 			goto error_local;
409 
410 			break;
411 	}
412 
413 	return result;
414 
415 	// Error trapping.
416     error_local:
417 
418 	printf("\nYou must provide a valid pointer, property name, and new value: " SELF_NAME "\n");
419 
420 	result = E_FAIL;
421 	return result;
422 
423     #undef SELF_NAME
424     #undef ARG_MINIMUM
425     #undef ARG_HANDLE
426     #undef ARG_PROPERTY
427     #undef ARG_VALUE
428 }
429 
430 // Caskey, Damon  V.
431 // 2018-10-11
432 //
433 // Run engine's internal bind update function.
openbor_update_bind(ScriptVariant ** varlist,ScriptVariant ** pretvar,int paramCount)434 HRESULT openbor_update_bind(ScriptVariant **varlist, ScriptVariant **pretvar, int paramCount)
435 {
436 #define SELF_NAME           "update_bind(void entity)"
437 #define ARG_MINIMUM         1   // Minimum required arguments.
438 #define ARG_ENTITY          0   // Target entity.
439 
440 	int		result	= S_OK;	// Success or error?
441 	entity	*ent	= NULL; // Target entity.
442 
443 	// Verify incoming arguments.
444 	if (paramCount < ARG_MINIMUM
445 		|| varlist[ARG_ENTITY]->vt != VT_PTR)
446 	{
447 		*pretvar = NULL;
448 		goto error_local;
449 	}
450 
451 	// Populate local handle and property vars.
452 	ent = (entity *)varlist[ARG_ENTITY]->ptrVal;
453 
454 	adjust_bind(ent);
455 
456 	return result;
457 
458 	// Error trapping.
459 error_local:
460 
461 	printf("You must provide a valid entity: " SELF_NAME "\n");
462 
463 	result = E_FAIL;
464 	return result;
465 
466 #undef SELF_NAME
467 #undef ARG_MINIMUM
468 #undef ARG_ENTITY
469 }