1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010 EDuke32 developers and contributors
4 
5 This file is part of EDuke32.
6 
7 EDuke32 is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License version 2
9 as published by the Free Software Foundation.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 
15 See the GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 */
21 //-------------------------------------------------------------------------
22 
23 // this is all the crap for accessing the game's structs through the CON VM
24 // I got a 3-4 fps gain by inlining these...
25 
26 #include "compat.h"
27 #include "m32script.h"
28 #include "m32def.h"
29 #ifdef POLYMER
30 # include "prlights.h"
31 #endif
32 
33 // how: bitfield: 1=set? 2=vars? 4=use spriteext[].tspr? (otherwise use tsprite[])
34 #define ACCESS_SET 1
35 #define ACCESS_USEVARS 2
36 
37 
38 /// This file is #included into other files, so don't define variables here!
39 
40 
VM_AccessWall(int32_t how,int32_t lVar1,int32_t labelNum,int32_t lVar2)41 static int32_t __fastcall VM_AccessWall(int32_t how, int32_t lVar1, int32_t labelNum, int32_t lVar2)
42 {
43     int32_t lValue;
44     int32_t i = (how&ACCESS_USEVARS) ? Gv_GetVar(lVar1) : lVar1;
45 
46     if (!m32_script_expertmode && (i<0 || i >= numwalls))
47         goto badwall;
48 
49     if (how&ACCESS_SET)
50     {
51         if (!m32_script_expertmode && (WallLabels[labelNum].flags & 1))
52             goto readonly;
53 
54         lValue = (how&ACCESS_USEVARS) ? Gv_GetVar(lVar2) : lVar2;
55 
56         asksave = 1;
57 
58         if (!m32_script_expertmode && (WallLabels[labelNum].min != 0 || WallLabels[labelNum].max != 0))
59         {
60             if (lValue < WallLabels[labelNum].min)
61                 lValue = WallLabels[labelNum].min;
62             if (lValue > WallLabels[labelNum].max)
63                 lValue = WallLabels[labelNum].max;
64         }
65 
66         switch (labelNum)
67         {
68         case WALL_X: wall[i].x=lValue; break;
69         case WALL_Y: wall[i].y=lValue; break;
70         case WALL_POINT2: wall[i].point2=lValue; break;
71         case WALL_NEXTWALL: wall[i].nextwall=lValue; break;
72         case WALL_NEXTSECTOR: wall[i].nextsector=lValue; break;
73         case WALL_CSTAT:
74 #ifdef YAX_ENABLE__COMPAT
75             if (!m32_script_expertmode)
76                 SET_PROTECT_BITS(wall[i].cstat, lValue, YAX_NEXTWALLBITS);
77             else
78 #endif
79                 wall[i].cstat = lValue;
80             break;
81         case WALL_PICNUM: wall[i].picnum=lValue; break;
82         case WALL_OVERPICNUM: wall[i].overpicnum=lValue; break;
83         case WALL_SHADE: wall[i].shade=lValue; break;
84         case WALL_PAL: wall[i].pal=lValue; break;
85         case WALL_XREPEAT: wall[i].xrepeat=lValue; break;
86         case WALL_YREPEAT: wall[i].yrepeat=lValue; break;
87         case WALL_XPANNING: wall[i].xpanning=lValue; break;
88         case WALL_YPANNING: wall[i].ypanning=lValue; break;
89         case WALL_LOTAG:
90 #ifdef YAX_ENABLE__COMPAT
91             if (!m32_script_expertmode && numyaxbunches>0 && yax_getnextwall(i,YAX_CEILING)>=0)
92                 goto yax_readonly;
93 #endif
94             wall[i].lotag=lValue;
95             break;
96         case WALL_HITAG: wall[i].hitag=lValue; break;
97         case WALL_EXTRA:
98 #ifdef YAX_ENABLE__COMPAT
99             if (!m32_script_expertmode && numyaxbunches>0 && yax_getnextwall(i,YAX_FLOOR)>=0)
100                 goto yax_readonly;
101 #endif
102             wall[i].extra=lValue;
103             break;
104         default:
105             return -1;
106         }
107 
108         return 0;
109     }
110     else
111     {
112         switch (labelNum)
113         {
114         case WALL_X: lValue=wall[i].x; break;
115         case WALL_Y: lValue=wall[i].y; break;
116         case WALL_POINT2: lValue=wall[i].point2; break;
117         case WALL_NEXTWALL: lValue=wall[i].nextwall; break;
118         case WALL_NEXTSECTOR: lValue=wall[i].nextsector; break;
119         case WALL_CSTAT: lValue=wall[i].cstat; break;
120         case WALL_PICNUM: lValue=wall[i].picnum; break;
121         case WALL_OVERPICNUM: lValue=wall[i].overpicnum; break;
122         case WALL_SHADE: lValue=wall[i].shade; break;
123         case WALL_PAL: lValue=wall[i].pal; break;
124         case WALL_XREPEAT: lValue=wall[i].xrepeat; break;
125         case WALL_YREPEAT: lValue=wall[i].yrepeat; break;
126         case WALL_XPANNING: lValue=wall[i].xpanning; break;
127         case WALL_YPANNING: lValue=wall[i].ypanning; break;
128         case WALL_LOTAG: lValue=wall[i].lotag; break;
129         case WALL_HITAG: lValue=wall[i].hitag; break;
130         case WALL_EXTRA: lValue=wall[i].extra; break;
131         default:
132             return -1;
133         }
134 
135         if (how&ACCESS_USEVARS)
136             Gv_SetVar(lVar2, lValue);
137 
138         return lValue;
139     }
140 
141 badwall:
142     M32_ERROR("Invalid wall %d", i);
143     return -1;
144 readonly:
145     M32_ERROR("Wall structure member `%s' is read-only.", WallLabels[labelNum].name);
146     return -1;
147 #ifdef YAX_ENABLE__COMPAT
148 yax_readonly:
149     M32_ERROR("Wall structure member `%s' is read-only because it is used for TROR",
150               WallLabels[labelNum].name);
151     return -1;
152 #endif
153 }
154 
155 // how: bitfield: 1=set? 2=vars?
VM_AccessSector(int32_t how,int32_t lVar1,int32_t labelNum,int32_t lVar2)156 static int32_t __fastcall VM_AccessSector(int32_t how, int32_t lVar1, int32_t labelNum, int32_t lVar2)
157 {
158     int32_t lValue;
159     int32_t i = (how&ACCESS_USEVARS) ? sprite[vm.spriteNum].sectnum : lVar1;
160 
161     if ((how&ACCESS_USEVARS) && lVar1 != M32_THISACTOR_VAR_ID)
162         i = Gv_GetVar(lVar1);
163 
164     if (!m32_script_expertmode && (i<0 || i >= numsectors))
165         goto badsector;
166 
167     if (how&ACCESS_SET)
168     {
169         if (!m32_script_expertmode && (SectorLabels[labelNum].flags & 1))
170             goto readonly;
171 
172         lValue = (how&ACCESS_USEVARS) ? Gv_GetVar(lVar2) : lVar2;
173 
174         asksave = 1;
175 
176         if (!m32_script_expertmode && (SectorLabels[labelNum].min != 0 || SectorLabels[labelNum].max != 0))
177         {
178             if (lValue < SectorLabels[labelNum].min)
179                 lValue = SectorLabels[labelNum].min;
180             if (lValue > SectorLabels[labelNum].max)
181                 lValue = SectorLabels[labelNum].max;
182         }
183 
184         switch (labelNum)
185         {
186         case SECTOR_WALLPTR: sector[i].wallptr=lValue; break;
187         case SECTOR_WALLNUM: sector[i].wallnum=lValue; break;
188         case SECTOR_CEILINGZ: sector[i].ceilingz=lValue; break;
189         case SECTOR_FLOORZ: sector[i].floorz=lValue; break;
190         case SECTOR_CEILINGSTAT:
191 #ifdef YAX_ENABLE__COMPAT
192             if (!m32_script_expertmode)
193                 SET_PROTECT_BITS(sector[i].ceilingstat, lValue, YAX_BIT);
194             else
195 #endif
196                 sector[i].ceilingstat = lValue;
197             break;
198         case SECTOR_FLOORSTAT:
199 #ifdef YAX_ENABLE__COMPAT
200             if (!m32_script_expertmode)
201                 SET_PROTECT_BITS(sector[i].floorstat, lValue, YAX_BIT);
202             else
203 #endif
204                 sector[i].floorstat = lValue;
205             break;
206         case SECTOR_CEILINGPICNUM: sector[i].ceilingpicnum=lValue; break;
207         case SECTOR_CEILINGSLOPE:
208             setslope(i, 0, lValue);
209             break;
210         case SECTOR_CEILINGSHADE: sector[i].ceilingshade=lValue; break;
211         case SECTOR_CEILINGPAL: sector[i].ceilingpal=lValue; break;
212         case SECTOR_CEILINGXPANNING: sector[i].ceilingxpanning=lValue; break;
213         case SECTOR_CEILINGYPANNING: sector[i].ceilingypanning=lValue; break;
214         case SECTOR_FLOORPICNUM: sector[i].floorpicnum=lValue; break;
215         case SECTOR_FLOORSLOPE:
216             setslope(i, 1, lValue);
217             break;
218         case SECTOR_FLOORSHADE: sector[i].floorshade=lValue; break;
219         case SECTOR_FLOORPAL: sector[i].floorpal=lValue; break;
220         case SECTOR_FLOORXPANNING: sector[i].floorxpanning=lValue; break;
221         case SECTOR_FLOORYPANNING: sector[i].floorypanning=lValue; break;
222         case SECTOR_VISIBILITY: sector[i].visibility=lValue; break;
223         case SECTOR_FOGPAL: sector[i].fogpal=lValue; break;
224         case SECTOR_LOTAG: sector[i].lotag=lValue; break;
225         case SECTOR_HITAG: sector[i].hitag=lValue; break;
226         case SECTOR_EXTRA: sector[i].extra=lValue; break;
227         default:
228             return -1;
229         }
230 
231         return 0;
232     }
233     else
234     {
235         switch (labelNum)
236         {
237         case SECTOR_WALLPTR: lValue=sector[i].wallptr; break;
238         case SECTOR_WALLNUM: lValue=sector[i].wallnum; break;
239         case SECTOR_CEILINGZ: lValue=sector[i].ceilingz; break;
240         case SECTOR_FLOORZ: lValue=sector[i].floorz; break;
241         case SECTOR_CEILINGSTAT: lValue=sector[i].ceilingstat; break;
242         case SECTOR_FLOORSTAT: lValue=sector[i].floorstat; break;
243         case SECTOR_CEILINGPICNUM: lValue=sector[i].ceilingpicnum; break;
244         case SECTOR_CEILINGSLOPE: lValue=sector[i].ceilingheinum; break;
245         case SECTOR_CEILINGSHADE: lValue=sector[i].ceilingshade; break;
246         case SECTOR_CEILINGPAL: lValue=sector[i].ceilingpal; break;
247         case SECTOR_CEILINGXPANNING: lValue=sector[i].ceilingxpanning; break;
248         case SECTOR_CEILINGYPANNING: lValue=sector[i].ceilingypanning; break;
249         case SECTOR_FLOORPICNUM: lValue=sector[i].floorpicnum; break;
250         case SECTOR_FLOORSLOPE: lValue=sector[i].floorheinum; break;
251         case SECTOR_FLOORSHADE: lValue=sector[i].floorshade; break;
252         case SECTOR_FLOORPAL: lValue=sector[i].floorpal; break;
253         case SECTOR_FLOORXPANNING: lValue=sector[i].floorxpanning; break;
254         case SECTOR_FLOORYPANNING: lValue=sector[i].floorypanning; break;
255         case SECTOR_VISIBILITY: lValue=sector[i].visibility; break;
256         case SECTOR_FOGPAL: lValue=sector[i].fogpal; break;
257         case SECTOR_LOTAG: lValue=sector[i].lotag; break;
258         case SECTOR_HITAG: lValue=sector[i].hitag; break;
259         case SECTOR_EXTRA: lValue=sector[i].extra; break;
260         default:
261             return -1;
262         }
263 
264         if (how&ACCESS_USEVARS)
265             Gv_SetVar(lVar2, lValue);
266 
267         return lValue;
268     }
269 
270 badsector:
271     M32_ERROR("Invalid sector %d", i);
272     return -1;
273 readonly:
274     M32_ERROR("Sector structure member `%s' is read-only.", SectorLabels[labelNum].name);
275     return -1;
276 }
277 
278 // how: bitfield: 1=set? 2=vars?
VM_AccessSprite(int32_t how,int32_t lVar1,int32_t labelNum,int32_t lVar2)279 static int32_t __fastcall VM_AccessSprite(int32_t how, int32_t lVar1, int32_t labelNum, int32_t lVar2)
280 {
281     int32_t lValue;
282     int32_t i = (how&ACCESS_USEVARS) ? vm.spriteNum : lVar1;
283 
284     if ((how&ACCESS_USEVARS) && lVar1 != M32_THISACTOR_VAR_ID)
285         i = Gv_GetVar(lVar1);
286 
287     if ((unsigned)i >= MAXSPRITES)
288         goto badsprite;
289 
290     if (how&ACCESS_SET)
291     {
292         if (!m32_script_expertmode && (SpriteLabels[labelNum].flags & 1))
293             goto readonly;
294 
295         lValue = (how&ACCESS_USEVARS) ? Gv_GetVar(lVar2) : lVar2;
296 
297         asksave = 1;
298 
299         if (!m32_script_expertmode && (SpriteLabels[labelNum].min != 0 || SpriteLabels[labelNum].max != 0))
300         {
301             if (lValue < SpriteLabels[labelNum].min)
302                 lValue = SpriteLabels[labelNum].min;
303             if (lValue > SpriteLabels[labelNum].max)
304                 lValue = SpriteLabels[labelNum].max;
305         }
306 
307         switch (labelNum)
308         {
309         case SPRITE_X: sprite[i].x=lValue; break;
310         case SPRITE_Y: sprite[i].y=lValue; break;
311         case SPRITE_Z: sprite[i].z=lValue; break;
312         case SPRITE_CSTAT: sprite[i].cstat = lValue; break;
313         case SPRITE_PICNUM: sprite[i].picnum=lValue; break;
314         case SPRITE_SHADE: sprite[i].shade=lValue; break;
315         case SPRITE_PAL: sprite[i].pal=lValue; break;
316         case SPRITE_CLIPDIST: sprite[i].clipdist=lValue; break;
317         case SPRITE_BLEND: sprite[i].blend=lValue; break;
318         case SPRITE_XREPEAT: sprite[i].xrepeat=lValue; break;
319         case SPRITE_YREPEAT: sprite[i].yrepeat=lValue; break;
320         case SPRITE_XOFFSET: sprite[i].xoffset=lValue; break;
321         case SPRITE_YOFFSET: sprite[i].yoffset=lValue; break;
322         case SPRITE_SECTNUM: changespritesect(i,lValue); break;
323         case SPRITE_STATNUM: changespritestat(i,lValue); break;
324         case SPRITE_ANG:
325             sprite[i].ang = lValue&2047;
326             break;
327         case SPRITE_OWNER: sprite[i].owner=lValue; break;
328         case SPRITE_XVEL: sprite[i].xvel=lValue; break;
329         case SPRITE_YVEL: sprite[i].yvel=lValue; break;
330         case SPRITE_ZVEL: sprite[i].zvel=lValue; break;
331         case SPRITE_LOTAG: sprite[i].lotag=lValue; break;
332         case SPRITE_HITAG: sprite[i].hitag=lValue; break;
333         case SPRITE_EXTRA: sprite[i].extra=lValue; break;
334         default:
335             return -1;
336         }
337 
338         return 0;
339     }
340     else
341     {
342         switch (labelNum)
343         {
344         case SPRITE_X: lValue=sprite[i].x; break;
345         case SPRITE_Y: lValue=sprite[i].y; break;
346         case SPRITE_Z: lValue=sprite[i].z; break;
347         case SPRITE_CSTAT: lValue=sprite[i].cstat; break;
348         case SPRITE_PICNUM: lValue=sprite[i].picnum; break;
349         case SPRITE_SHADE: lValue=sprite[i].shade; break;
350         case SPRITE_PAL: lValue=sprite[i].pal; break;
351         case SPRITE_CLIPDIST: lValue=sprite[i].clipdist; break;
352         case SPRITE_BLEND: lValue=sprite[i].blend; break;
353         case SPRITE_XREPEAT: lValue=sprite[i].xrepeat; break;
354         case SPRITE_YREPEAT: lValue=sprite[i].yrepeat; break;
355         case SPRITE_XOFFSET: lValue=sprite[i].xoffset; break;
356         case SPRITE_YOFFSET: lValue=sprite[i].yoffset; break;
357         case SPRITE_SECTNUM: lValue=sprite[i].sectnum; break;
358         case SPRITE_STATNUM: lValue=sprite[i].statnum; break;
359         case SPRITE_ANG: lValue=sprite[i].ang; break;
360         case SPRITE_OWNER: lValue=sprite[i].owner; break;
361         case SPRITE_XVEL: lValue=sprite[i].xvel; break;
362         case SPRITE_YVEL: lValue=sprite[i].yvel; break;
363         case SPRITE_ZVEL: lValue=sprite[i].zvel; break;
364         case SPRITE_LOTAG: lValue=sprite[i].lotag; break;
365         case SPRITE_HITAG: lValue=sprite[i].hitag; break;
366         case SPRITE_EXTRA: lValue=sprite[i].extra; break;
367         default:
368             return -1;
369         }
370 
371         if (how&ACCESS_USEVARS)
372             Gv_SetVar(lVar2, lValue);
373 
374         return lValue;
375     }
376 badsprite:
377     M32_ERROR("tried to set %s on invalid target sprite (%d)", SpriteLabels[labelNum].name, i);
378     return -1;
379 readonly:
380     M32_ERROR("sprite structure member `%s' is read-only.", SpriteLabels[labelNum].name);
381     return -1;
382 }
383 
384 // how: bitfield: 1=set? 2=vars? 4=use spriteext[].tspr? (otherwise use tsprite[])
VM_AccessTsprite(int32_t how,int32_t lVar1,int32_t labelNum,int32_t lVar2)385 static int32_t __fastcall VM_AccessTsprite(int32_t how, int32_t lVar1, int32_t labelNum, int32_t lVar2)
386 {
387     int32_t lightp = (labelNum >= LIGHT_X);
388     int32_t i = (how&ACCESS_USEVARS) ? vm.spriteNum : lVar1;
389     tspriteptr_t datspr = nullptr;
390     memberlabel_t const *dalabel = lightp ? &LightLabels[labelNum-LIGHT_X] : &SpriteLabels[labelNum];
391 
392     if ((how&ACCESS_USEVARS) && lVar1 != M32_THISACTOR_VAR_ID)
393         i = Gv_GetVar(lVar1);
394 
395     if (!lightp)
396     {
397         if (i<0 || i>=spritesortcnt)
398             goto badsprite;
399         datspr = &tsprite[i];
400     }
401     else
402     {
403         // access Polymer light
404 #ifndef POLYMER
405         M32_ERROR("Polymer not compiled in, accessing lights is invalid.");
406         return -1;
407 #else
408         if ((how&ACCESS_USEVARS) && lVar1 == M32_THISACTOR_VAR_ID)
409         {
410             if ((unsigned)i >= MAXSPRITES)
411                 goto badsprite;
412             M32_ERROR("Polymer light access via current sprite not implemented.");
413             return -1;
414         }
415         else
416         {
417 // check whether videoGetRenderMode() == REND_POLYMER ?
418             if ((unsigned)i >= PR_MAXLIGHTS)
419             {
420                 M32_ERROR("invalid light index (%d)", i);
421                 return -1;
422             }
423 
424             if (labelNum != LIGHT_ACTIVE && !prlights[i].flags.active)
425             {
426                 M32_ERROR("light with index %d is inactive!", i);
427                 return -1;
428             }
429         }
430 #endif
431     }
432 
433     if (how&ACCESS_SET)
434     {
435         int32_t lValue, damin, damax;
436 
437         if (!m32_script_expertmode && (dalabel->flags & 1))
438             goto readonly;
439 
440         lValue = (how&ACCESS_USEVARS) ? Gv_GetVar(lVar2) : lVar2;
441 
442         damin = dalabel->min;
443         damax = dalabel->max;
444 
445         if (!m32_script_expertmode && (damin|damax))
446         {
447             if (lValue < damin)
448                 lValue = damin;
449             if (lValue > damax)
450                 lValue = damax;
451         }
452 
453         switch (labelNum)
454         {
455         case SPRITE_X: datspr->x=lValue; break;
456         case SPRITE_Y: datspr->y=lValue; break;
457         case SPRITE_Z: datspr->z=lValue; break;
458         case SPRITE_CSTAT: datspr->cstat = lValue; break;
459         case SPRITE_PICNUM: datspr->picnum=lValue; break;
460         case SPRITE_SHADE: datspr->shade=lValue; break;
461         case SPRITE_PAL: datspr->pal=lValue; break;
462         case SPRITE_CLIPDIST: datspr->clipdist=lValue; break;
463         case SPRITE_BLEND: datspr->blend=lValue; break;
464         case SPRITE_XREPEAT: datspr->xrepeat=lValue; break;
465         case SPRITE_YREPEAT: datspr->yrepeat=lValue; break;
466         case SPRITE_XOFFSET: datspr->xoffset=lValue; break;
467         case SPRITE_YOFFSET: datspr->yoffset=lValue; break;
468         case SPRITE_SECTNUM: datspr->sectnum=lValue; break;
469         case SPRITE_STATNUM: datspr->statnum=lValue; break;
470         case SPRITE_ANG:
471             datspr->ang = lValue&2047;
472             break;
473         case SPRITE_OWNER: datspr->owner=lValue; break;
474         case SPRITE_XVEL: datspr->xvel=lValue; break;
475         case SPRITE_YVEL: datspr->yvel=lValue; break;
476         case SPRITE_ZVEL: datspr->zvel=lValue; break;
477         case SPRITE_LOTAG: datspr->lotag=lValue; break;
478         case SPRITE_HITAG: datspr->hitag=lValue; break;
479         case SPRITE_EXTRA: datspr->extra=lValue; break;
480 #ifdef POLYMER
481         // lights
482         case LIGHT_X: prlights[i].x = lValue; break;
483         case LIGHT_Y: prlights[i].y = lValue; break;
484         case LIGHT_Z: prlights[i].z = lValue; break;
485         case LIGHT_HORIZ: prlights[i].horiz = lValue; break;
486         case LIGHT_RANGE: prlights[i].range = lValue; break;
487         case LIGHT_ANGLE: prlights[i].angle = lValue; break;
488         case LIGHT_FADERADIUS: prlights[i].faderadius = lValue; break;
489         case LIGHT_RADIUS: prlights[i].radius = lValue; break;
490         case LIGHT_SECTOR: prlights[i].sector = lValue; break;
491         case LIGHT_R: prlights[i].color[0] = lValue; break;
492         case LIGHT_G: prlights[i].color[1] = lValue; break;
493         case LIGHT_B: prlights[i].color[2] = lValue; break;
494         case LIGHT_PRIORITY: prlights[i].priority = lValue; break;
495         case LIGHT_TILENUM: prlights[i].tilenum = lValue; break;
496         case LIGHT_MINSHADE: prlights[i].minshade = lValue; break;
497         case LIGHT_MAXSHADE: prlights[i].maxshade = lValue; break;
498 #endif
499         default:
500             return -1;
501         }
502 
503         return 0;
504     }
505     else
506     {
507         int32_t lValue;
508 
509         switch (labelNum)
510         {
511         case SPRITE_X: lValue=datspr->x; break;
512         case SPRITE_Y: lValue=datspr->y; break;
513         case SPRITE_Z: lValue=datspr->z; break;
514         case SPRITE_CSTAT: lValue=datspr->cstat; break;
515         case SPRITE_PICNUM: lValue=datspr->picnum; break;
516         case SPRITE_SHADE: lValue=datspr->shade; break;
517         case SPRITE_PAL: lValue=datspr->pal; break;
518         case SPRITE_CLIPDIST: lValue=datspr->clipdist; break;
519         case SPRITE_BLEND: lValue=datspr->blend; break;
520         case SPRITE_XREPEAT: lValue=datspr->xrepeat; break;
521         case SPRITE_YREPEAT: lValue=datspr->yrepeat; break;
522         case SPRITE_XOFFSET: lValue=datspr->xoffset; break;
523         case SPRITE_YOFFSET: lValue=datspr->yoffset; break;
524         case SPRITE_SECTNUM: lValue=datspr->sectnum; break;
525         case SPRITE_STATNUM: lValue=datspr->statnum; break;
526         case SPRITE_ANG: lValue=datspr->ang; break;
527         case SPRITE_OWNER: lValue=datspr->owner; break;
528         case SPRITE_XVEL: lValue=datspr->xvel; break;
529         case SPRITE_YVEL: lValue=datspr->yvel; break;
530         case SPRITE_ZVEL: lValue=datspr->zvel; break;
531         case SPRITE_LOTAG: lValue=datspr->lotag; break;
532         case SPRITE_HITAG: lValue=datspr->hitag; break;
533         case SPRITE_EXTRA: lValue=datspr->extra; break;
534 #ifdef POLYMER
535         // lights
536         case LIGHT_X: lValue = prlights[i].x; break;
537         case LIGHT_Y: lValue = prlights[i].y; break;
538         case LIGHT_Z: lValue = prlights[i].z; break;
539         case LIGHT_HORIZ: lValue = prlights[i].horiz; break;
540         case LIGHT_RANGE: lValue = prlights[i].range; break;
541         case LIGHT_ANGLE: lValue = prlights[i].angle; break;
542         case LIGHT_FADERADIUS: lValue = prlights[i].faderadius; break;
543         case LIGHT_RADIUS: lValue = prlights[i].radius; break;
544         case LIGHT_SECTOR: lValue = prlights[i].sector; break;
545         case LIGHT_R: lValue = prlights[i].color[0]; break;
546         case LIGHT_G: lValue = prlights[i].color[1]; break;
547         case LIGHT_B: lValue = prlights[i].color[2]; break;
548         case LIGHT_PRIORITY: lValue = prlights[i].priority; break;
549         case LIGHT_TILENUM: lValue = prlights[i].tilenum; break;
550         case LIGHT_MINSHADE: lValue = prlights[i].minshade; break;
551         case LIGHT_MAXSHADE: lValue = prlights[i].maxshade; break;
552         case LIGHT_ACTIVE: lValue = !!prlights[i].flags.active; break;
553 #endif
554         default:
555             return -1;
556         }
557 
558         if (how&ACCESS_USEVARS)
559             Gv_SetVar(lVar2, lValue);
560 
561         return lValue;
562     }
563 
564 badsprite:
565     M32_ERROR("invalid target sprite (%d)", i);
566     return -1;
567 readonly:
568     M32_ERROR("structure member `%s' is read-only.", dalabel->name);
569     return -1;
570 }
571 
572 #undef ACCESS_SET
573 #undef ACCESS_USEVARS
574