1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * 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 // Handles effect polygons.
24 //
25 // EffectPolyProcess() monitors triggering of effect code (i.e. a moving
26 // actor entering an effect polygon).
27 // EffectProcess() runs the appropriate effect code.
28 //
29 // NOTE: Currently will only run one effect process at a time, i.e.
30 // effect polygons will not currently nest. It won't be very difficult
31 // to fix this if required.
32
33 #include "tinsel/actors.h"
34 #include "tinsel/dw.h"
35 #include "tinsel/events.h"
36 #include "tinsel/pid.h"
37 #include "tinsel/pcode.h" // LEAD_ACTOR
38 #include "tinsel/polygons.h"
39 #include "tinsel/movers.h"
40 #include "tinsel/sched.h"
41 #include "tinsel/tinsel.h"
42
43
44 namespace Tinsel {
45
46 struct EP_INIT {
47 HPOLYGON hEpoly;
48 PMOVER pMover;
49 int index;
50 };
51
52 /**
53 * Runs an effect polygon's Glitter code with ENTER event, waits for the
54 * actor to leave that polygon. Then runs the polygon's Glitter code
55 * with LEAVE event.
56 */
EffectProcess(CORO_PARAM,const void * param)57 static void EffectProcess(CORO_PARAM, const void *param) {
58 // COROUTINE
59 CORO_BEGIN_CONTEXT;
60 CORO_END_CONTEXT(_ctx);
61
62 const EP_INIT *to = (const EP_INIT *)param; // get the stuff copied to process when it was created
63
64 CORO_BEGIN_CODE(_ctx);
65
66 int x, y; // Lead actor position
67
68 // Run effect poly enter script
69 if (TinselV2)
70 CORO_INVOKE_ARGS(PolygonEvent, (CORO_SUBCTX, to->hEpoly, WALKIN,
71 GetMoverId(to->pMover), false, 0));
72 else
73 effRunPolyTinselCode(to->hEpoly, WALKIN, to->pMover->actorID);
74
75 do {
76 CORO_SLEEP(1);
77 GetMoverPosition(to->pMover, &x, &y);
78 } while (InPolygon(x, y, EFFECT) == to->hEpoly);
79
80 // Run effect poly leave script
81 if (TinselV2)
82 CORO_INVOKE_ARGS(PolygonEvent, (CORO_SUBCTX, to->hEpoly, WALKOUT,
83 GetMoverId(to->pMover), false, 0));
84 else
85 effRunPolyTinselCode(to->hEpoly, WALKOUT, to->pMover->actorID);
86
87 SetMoverInEffect(to->index, false);
88
89 CORO_END_CODE;
90 }
91
92 /**
93 * If the actor was not already in an effect polygon, checks to see if
94 * it has just entered one. If it has, a process is started up to run
95 * the polygon's Glitter code.
96 */
FettleEffectPolys(int x,int y,int index,PMOVER pActor)97 static void FettleEffectPolys(int x, int y, int index, PMOVER pActor) {
98 HPOLYGON hPoly;
99 EP_INIT epi;
100
101 // If just entered an effect polygon, the effect should be triggered.
102 if (!IsMAinEffectPoly(index)) {
103 hPoly = InPolygon(x, y, EFFECT);
104 if (hPoly != NOPOLY) {
105 //Just entered effect polygon
106 SetMoverInEffect(index, true);
107
108 epi.hEpoly = hPoly;
109 epi.pMover = pActor;
110 epi.index = index;
111 CoroScheduler.createProcess(PID_TCODE, EffectProcess, &epi, sizeof(epi));
112 }
113 }
114 }
115
116 /**
117 * Just calls FettleEffectPolys() every clock tick.
118 */
EffectPolyProcess(CORO_PARAM,const void * param)119 void EffectPolyProcess(CORO_PARAM, const void *param) {
120 // COROUTINE
121 CORO_BEGIN_CONTEXT;
122 CORO_END_CONTEXT(_ctx);
123
124 CORO_BEGIN_CODE(_ctx);
125 while (1) {
126 for (int i = 0; i < MAX_MOVERS; i++) {
127 PMOVER pActor = GetLiveMover(i);
128 if (pActor != NULL) {
129 int x, y;
130 GetMoverPosition(pActor, &x, &y);
131 FettleEffectPolys(x, y, i, pActor);
132 }
133 }
134
135 CORO_SLEEP(1); // allow re-scheduling
136 }
137 CORO_END_CODE;
138 }
139
140 } // End of namespace Tinsel
141