1 #include "char.h"
2 #include "map.h"
3 #include "game.h"
4 #include "gfx.h"
5 
6 CHAR list[MAX_CHARS];
7 int char_num = 1;
8 
9 /* Moving:
10 
11    main loop -> player_process(), monster_process()
12                              |      |
13 						    char_move()
14                                 |
15                                / \
16 						   step	  dx || dy
17 						    |        |
18 		   when step gets 0 |        |
19               change_position()    leave(), encounter()
20 
21 */
22 
23 /* C64: data
24 455 dataa,dire wolf,31,a,rogue,42
25 456 dataan,ogre,27,a,barbarian,41,a,hobgoblin,27,an,elvin ranger,41,a,werebear,27
26 457 dataa,dwarven guard,43,a,gargoyle,28,a,mercenary,41,a,troll,27,a,swordsman,41
27 458 dataa,wyvern,30,a,monk,41,a,dimension spider,29,a,dark warrior,41,a,shadow dragon,30
28 459 dataan,assassin,40,a,fyre drake,30,a,war lord,41
29 */
30 
31 char const *char_names[CHAR_NUM] = {
32 	"you",
33 	"Rogue",
34 	"Barbarian",
35 	"Elvin Ranger",
36 	"Dwarven Guard",
37 	"Mercenary",
38 	"Swordsman",
39 	"Monk",
40 	"Dark Warrior",
41 	"Assassin",
42 	"War Lord",
43 	"Dire Wolf",
44 	"Ogre",
45 	"Hobgoblin",
46 	"Werebear",
47 	"Gargoyle",
48 	"Troll",
49 	"Wyvern",
50 	"Dimension Spider",
51 	"Shadow Dragon",
52 	"Fyre Drake"
53 };
54 
55 char const *char_prefixes[CHAR_NUM][3] = {
56 	{"", "", ""},
57 	{"a", "an inferior", "an experienced"},
58 	{"a", "an inferior", "an experienced"},
59 	{"an", "an inferior", "an experienced"},
60 	{"a", "an inferior", "an experienced"},
61 	{"a", "an inferior", "an experienced"},
62 	{"a", "an inferior", "an experienced"},
63 	{"a", "an inferior", "an experienced"},
64 	{"a", "an inferior", "an experienced"},
65 	{"an", "an inferior", "an experienced"},
66 	{"a", "an inferior", "an experienced"},
67 	{"a", "a weak", "a powerful"},
68 	{"an", "a weak", "a powerful"},
69 	{"a", "a weak", "a powerful"},
70 	{"a", "a weak", "a powerful"},
71 	{"a", "a weak", "a powerful"},
72 	{"a", "a weak", "a powerful"},
73 	{"a", "a weak", "a powerful"},
74 	{"a", "a weak", "a powerful"},
75 	{"a", "a weak", "a powerful"},
76 	{"a", "a weak", "a powerful"}
77 };
78 
79 void
chars_init(void)80 chars_init (void)
81 {
82 
83 }
84 
85 int
char_create(int x,int y)86 char_create (int x, int y)
87 {
88 	int id;
89 
90 	if (char_num == MAX_CHARS)
91 		return 0;
92 
93 	for (id = 1; id < char_num; id++)
94 	{
95 		if (!list[id].alive)
96 			break;
97 	}
98 	if (id == MAX_CHARS)
99 		return 0;
100 	if (id == char_num)
101 		char_num++;
102 
103 	memset (&list[id], 0, sizeof list[id]);
104 
105 	list[id].x = x;
106 	list[id].y = y;
107 	list[id].alive = 1;
108 
109 	return id;
110 }
111 
112 /**
113  * Called by char_move when a character encounters another one.
114  */
115 static int
encounter(int id,int who)116 encounter (int id, int who)
117 {
118 	if (who == 1 && map_get_spot (list[who].x, list[who].y) != SPOT_TEMPLE &&
119 		map_get_spot (list[who].x, list[who].y) != SPOT_BEACON/* &&
120 		!list[who].step*/)
121 	{
122 		if (!list[who].fighting && list[who].alive)
123 		{
124 			list[id].fighting = who;
125 			list[who].fighting = id;
126 			list[who].attacked = 1;
127 			message (FPS * 2, attack, "Attacked by %s %s!",
128 				char_prefixes[list[id].type][list[id].subtype],
129 				char_names[list[id].type]);
130 			return 1;
131 		}
132 	}
133 	if (id == 1)
134 	{
135 		if (!list[id].fighting)
136 		{
137 			list[id].fighting = who;
138 			list[who].fighting = id;
139 			list[who].attacked = 1;
140 			message (FPS * 2, fight, "%c%s %s!",
141 				toupper (char_prefixes[list[who].type][list[who].subtype][0]),
142 				char_prefixes[list[who].type][list[who].subtype] + 1,
143 				char_names[list[who].type]);
144 			return 1;
145 		}
146 	}
147 	return 0;
148 }
149 
150 /**
151  * Called by char_move whenever a character leaves his current position.
152  */
153 static void
leave(int id)154 leave (int id)
155 {
156 	if (id == 1)
157 	{
158 		player_leave (id);
159 	}
160 }
161 
162 /**
163  * Called by char_move whenever a character changes to a new position.
164  */
165 static void
change_position(int id)166 change_position (int id)
167 {
168 	if (id == 1)
169 		player_change_position (id);
170 	else
171 		monster_change_position (id);
172 }
173 
174 /**
175  * Returns 0 if the character may not enter the given map position.
176  */
177 static int
may_walk(int id,int x,int y)178 may_walk (int id, int x, int y)
179 {
180 	if (id == 1 && !list[id].attacked && map_get_spot (x, y) != SPOT_WALL)
181 		return 1;
182 	if (id > 1 && map_get_spot (x, y) != SPOT_WALL)
183 		return 1;
184 	return 0;
185 }
186 
187 /**
188  * Processes movement of a character. If its is still moving, dx and dy are
189  * ignored. Else, the character tries to move in the given direction.
190  *
191  * Returns 1 if a move is initiated
192  **/
193 int
char_move(int id,int dx,int dy)194 char_move (int id, int dx, int dy)
195 {
196 	int x = list[id].x;
197 	int y = list[id].y;
198 
199 	if (!list[id].alive)
200 		return 0;
201 
202 	if (list[id].step)
203 	{
204 		int overlap;
205 
206 		overlap = (sprite_h + th - 1) / th - 1;
207 		list[id].step--;
208 
209 		DR_add (x - 1 - 1, y - overlap - 1, x + 1 + 1, y + 1);
210 
211 		if (!list[id].step)
212 			change_position (id);
213 	}
214 	else if (dx || dy)
215 	{
216 		int ok = 0;
217 		int ox, oy;
218 
219 		ox = x;
220 		oy = y;
221 
222 		if (may_walk (id, x + dx, y + dy))
223 			ok = 1;
224 		else if (dx && dy)
225 		{
226 			if (may_walk (id, x, y + dy))
227 			{
228 				ok = 1;
229 				dx = 0;
230 			}
231 			else if (may_walk (id, x + dx, y))
232 			{
233 				ok = 1;
234 				dy = 0;
235 			}
236 		}
237 
238 		if (ok)
239 		{
240 			int e = map_get_char (x + dx, y + dy);
241 			int go = 0;
242 			if (e == 0)
243 			{
244 				e=list[id].fighting;
245 				cancel_fighting (id);
246 				if(!e)
247 					go = 1;
248 				else
249 					go = 2;
250 			}
251 			else
252 			{
253 				if (extensions_overlapfight)
254 				{
255 					encounter (id, e);
256 					return 0;
257 				}
258 				else
259 				{
260 					int player_involved = (id == 1 || (e == 1 && !list[e].fighting));
261 					if (player_involved)
262 					{
263 						cancel_fighting (id);
264 						if (encounter (id, e))
265 							go = 1;
266 					}
267 				}
268 			}
269 
270 			if (go)
271 			{
272 				if(go==2 && !extensions_overlapfight)
273 					map_put_char (x, y, e);
274 				else
275 					map_put_char (x, y, 0);
276 
277 				leave (id);
278 
279 				x += dx;
280 				y += dy;
281 
282 				list[id].dx = dx;
283 				list[id].dy = dy;
284 				list[id].step = get_steptime();
285 				list[id].x = x;
286 				list[id].y = y;
287 
288 				map_put_char (x, y, id);
289 			}
290 		}
291 		else
292 		{
293 			return 0;
294 		}
295 
296 		return 1;
297 	}
298 	return 0;
299 }
300 
301 void
char_transfer_to(int id,int x,int y)302 char_transfer_to (int id, int x, int y)
303 {
304 	list[id].step = 0;
305 
306 	map_put_char (list[id].x, list[id].y, 0);
307 	cancel_fighting (id);
308 
309 	leave (id);
310 
311 	list[id].x = x;
312 	list[id].y = y;
313 	map_put_char (x, y, id);
314 
315 	change_position (id);
316 }
317 
318 int
char_teleport(int id)319 char_teleport (int id)
320 {
321 	int x = list[id].beaconx;
322 	int y = list[id].beacony;
323 
324 	if ((!x || !y) || list[1].trapped)
325 		do
326 		{
327 			x = rnd (1, MAP_W - 2);
328 			y = rnd (1, MAP_H - 2);
329 		}
330 		while (map_get_spot (x, y) != SPOT_FLOOR || map_get_char (x, y));
331 
332 	char_transfer_to (id, x, y);
333 	return 1;
334 }
335