aboutsummaryrefslogtreecommitdiff
path: root/engines/tinsel/effect.cpp
blob: f5adb63c2bae381c3f9f81e724fbacdc69656efd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

// Handles effect polygons.
//
// EffectPolyProcess() monitors triggering of effect code (i.e. a moving
// actor entering an effect polygon).
// EffectProcess() runs the appropriate effect code.
//
// NOTE: Currently will only run one effect process at a time, i.e.
// effect polygons will not currently nest. It won't be very difficult
// to fix this if required.

#include "tinsel/actors.h"
#include "tinsel/dw.h"
#include "tinsel/events.h"
#include "tinsel/pid.h"
#include "tinsel/pcode.h"		// LEAD_ACTOR
#include "tinsel/polygons.h"
#include "tinsel/rince.h"
#include "tinsel/sched.h"
#include "tinsel/tinsel.h"


namespace Tinsel {

struct EP_INIT {
	HPOLYGON	hEpoly;
	PMOVER		pMover;
	int		index;
};

/**
 * Runs an effect polygon's Glitter code with ENTER event, waits for the
 * actor to leave that polygon. Then runs the polygon's Glitter code
 * with LEAVE event.
 */
static void EffectProcess(CORO_PARAM, const void *param) {
	// COROUTINE
	CORO_BEGIN_CONTEXT;
	CORO_END_CONTEXT(_ctx);

	const EP_INIT *to = (const EP_INIT *)param;		// get the stuff copied to process when it was created

	CORO_BEGIN_CODE(_ctx);

	int		x, y;		// Lead actor position

	// Run effect poly enter script
	if (TinselV2)
		CORO_INVOKE_ARGS(PolygonEvent, (CORO_SUBCTX, to->hEpoly, WALKIN,
			GetMoverId(to->pMover), false, 0));
	else
		effRunPolyTinselCode(to->hEpoly, WALKIN, to->pMover->actorID);

	do {
		CORO_SLEEP(1);
		GetMoverPosition(to->pMover, &x, &y);
	} while (InPolygon(x, y, EFFECT) == to->hEpoly);

	// Run effect poly leave script
	if (TinselV2)
		CORO_INVOKE_ARGS(PolygonEvent, (CORO_SUBCTX, to->hEpoly, WALKOUT,
			GetMoverId(to->pMover), false, 0));
	else
		effRunPolyTinselCode(to->hEpoly, WALKOUT, to->pMover->actorID);

	SetMoverInEffect(to->index, false);

	CORO_END_CODE;
}

/**
 * If the actor was not already in an effect polygon, checks to see if
 * it has just entered one. If it has, a process is started up to run
 * the polygon's Glitter code.
 */
static void FettleEffectPolys(int x, int y, int index, PMOVER pActor) {
	HPOLYGON	hPoly;
	EP_INIT		epi;

	// If just entered an effect polygon, the effect should be triggered.
	if (!IsMAinEffectPoly(index)) {
		hPoly = InPolygon(x, y, EFFECT);
		if (hPoly != NOPOLY) {
			//Just entered effect polygon
			SetMoverInEffect(index, true);

			epi.hEpoly = hPoly;
			epi.pMover = pActor;
			epi.index = index;
			CoroScheduler.createProcess(PID_TCODE, EffectProcess, &epi, sizeof(epi));
		}
	}
}

/**
 * Just calls FettleEffectPolys() every clock tick.
 */
void EffectPolyProcess(CORO_PARAM, const void *param) {
	// COROUTINE
	CORO_BEGIN_CONTEXT;
	CORO_END_CONTEXT(_ctx);

	CORO_BEGIN_CODE(_ctx);
	while (1) {
		for (int i = 0; i < MAX_MOVERS; i++) {
			PMOVER pActor = GetLiveMover(i);
			if (pActor != NULL) {
				int	x, y;
				GetMoverPosition(pActor, &x, &y);
				FettleEffectPolys(x, y, i, pActor);
			}
		}

		CORO_SLEEP(1);		// allow re-scheduling
	}
	CORO_END_CODE;
}

} // End of namespace Tinsel