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