1 /*
2 SDLPoP, a port/conversion of the DOS game Prince of Persia.
3 Copyright (C) 2013-2021  Dávid Nagy
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18 The authors of this program may be contacted at https://forum.princed.org
19 */
20 
21 #include "common.h"
22 
23 // data:432F
24 sbyte bump_col_left_of_wall;
25 // data:436E
26 sbyte bump_col_right_of_wall;
27 // data:4C0A
28 sbyte right_checked_col;
29 // data:408A
30 sbyte left_checked_col;
31 
32 
33 // data:4C0C
34 short coll_tile_left_xpos;
35 // These two arrays are indexed with the return value of wall_type.
36 // data:24BA
37 const sbyte wall_dist_from_left[] = {0, 10, 0, -1, 0, 0};
38 // data:24C0
39 const sbyte wall_dist_from_right[] = {0, 0, 10, 13, 0, 0};
40 
41 // seg004:0004
check_collisions()42 void __pascal far check_collisions() {
43 	short column;
44 	bump_col_left_of_wall = bump_col_right_of_wall = -1;
45 	if (Char.action == actions_7_turn) return;
46 	collision_row = Char.curr_row;
47 	move_coll_to_prev();
48 	prev_collision_row = collision_row;
49 	right_checked_col = MIN(get_tile_div_mod_m7(char_x_right_coll) + 2, 11);
50 	left_checked_col = get_tile_div_mod_m7(char_x_left_coll) - 1;
51 	get_row_collision_data(collision_row    , curr_row_coll_room, curr_row_coll_flags);
52 	get_row_collision_data(collision_row + 1, below_row_coll_room, below_row_coll_flags);
53 	get_row_collision_data(collision_row - 1, above_row_coll_room, above_row_coll_flags);
54 	for (column = 9; column >= 0; --column) {
55 		if (curr_row_coll_room[column] >= 0 &&
56 			prev_coll_room[column] == curr_row_coll_room[column]
57 		) {
58 			// char bumps into left of wall
59 			if (
60 				(prev_coll_flags[column] & 0x0F) == 0 &&
61 				(curr_row_coll_flags[column] & 0x0F) != 0
62 			) {
63 				bump_col_left_of_wall = column;
64 			}
65 			// char bumps into right of wall
66 			if (
67 				(prev_coll_flags[column] & 0xF0) == 0 &&
68 				(curr_row_coll_flags[column] & 0xF0) != 0
69 			) {
70 				bump_col_right_of_wall = column;
71 			}
72 		}
73 	}
74 }
75 
76 // seg004:00DF
move_coll_to_prev()77 void __pascal far move_coll_to_prev() {
78 	sbyte* row_coll_room_ptr;
79 	byte* row_coll_flags_ptr;
80 	short column;
81 	if (collision_row     == prev_collision_row ||
82 		collision_row + 3 == prev_collision_row ||
83 		collision_row - 3 == prev_collision_row
84 	) {
85 		row_coll_room_ptr = curr_row_coll_room;
86 		row_coll_flags_ptr = curr_row_coll_flags;
87 	} else if (
88 		collision_row + 1 == prev_collision_row ||
89 		collision_row - 2 == prev_collision_row
90 	) {
91 		row_coll_room_ptr = above_row_coll_room;
92 		row_coll_flags_ptr = above_row_coll_flags;
93 	} else {
94 		row_coll_room_ptr = below_row_coll_room;
95 		row_coll_flags_ptr = below_row_coll_flags;
96 	}
97 	for (column = 0; column < 10; ++column) {
98 		prev_coll_room[column] = row_coll_room_ptr[column];
99 		prev_coll_flags[column] = row_coll_flags_ptr[column];
100 		below_row_coll_room[column] = -1;
101 		above_row_coll_room[column] = -1;
102 		curr_row_coll_room[column] = -1;
103 #ifdef FIX_COLL_FLAGS
104 		// bugfix:
105 		curr_row_coll_flags[column] = 0;
106 		below_row_coll_flags[column] = 0;
107 		above_row_coll_flags[column] = 0;
108 #endif
109 	}
110 }
111 
112 // seg004:0185
get_row_collision_data(short row,sbyte * row_coll_room_ptr,byte * row_coll_flags_ptr)113 void __pascal far get_row_collision_data(short row, sbyte *row_coll_room_ptr, byte *row_coll_flags_ptr) {
114 	short right_wall_xpos;
115 	byte curr_flags;
116 	short room;
117 	short column;
118 	short left_wall_xpos;
119 	room = Char.room;
120 	coll_tile_left_xpos = x_bump[left_checked_col + 5] + 7;
121 	for (column = left_checked_col; column <= right_checked_col; ++column) {
122 		left_wall_xpos = get_left_wall_xpos(room, column, row);
123 		right_wall_xpos = get_right_wall_xpos(room, column, row);
124 		// char bumps into left of wall
125 		curr_flags = (left_wall_xpos < char_x_right_coll) * 0x0F;
126 		// char bumps into right of wall
127 		curr_flags |= (right_wall_xpos > char_x_left_coll) * 0xF0;
128 		row_coll_flags_ptr[tile_col] = curr_flags;
129 		row_coll_room_ptr[tile_col] = curr_room;
130 		coll_tile_left_xpos += 14;
131 	}
132 }
133 
134 // seg004:0226
get_left_wall_xpos(int room,int column,int row)135 int __pascal far get_left_wall_xpos(int room,int column,int row) {
136 	short type;
137 	type = wall_type(get_tile(room, column, row));
138 	if (type) {
139 		return wall_dist_from_left[type] + coll_tile_left_xpos;
140 	} else {
141 		return 0xFF;
142 	}
143 }
144 
145 // seg004:025F
get_right_wall_xpos(int room,int column,int row)146 int __pascal far get_right_wall_xpos(int room,int column,int row) {
147 	short type;
148 	type = wall_type(get_tile(room, column, row));
149 	if (type) {
150 		return coll_tile_left_xpos - wall_dist_from_right[type] + 13;
151 	} else {
152 		return 0;
153 	}
154 }
155 
156 // seg004:029D
check_bumped()157 void __pascal far check_bumped() {
158 	if (
159 		Char.action != actions_2_hang_climb &&
160 		Char.action != actions_6_hang_straight &&
161 		// frames 135..149: climb up
162 		(Char.frame < frame_135_climbing_1 || Char.frame >= 149)
163 	) {
164 #ifdef FIX_TWO_COLL_BUG
165 		if (bump_col_left_of_wall >= 0) {
166 			check_bumped_look_right();
167 			if (!fixes->fix_two_coll_bug) return; // check for the left-oriented collision only with the fix enabled
168 		}
169 		if (bump_col_right_of_wall >= 0) {
170 			check_bumped_look_left();
171 		}
172 #else
173 		if (bump_col_left_of_wall >= 0) {
174 			check_bumped_look_right();
175 		}
176 		else
177 		if (bump_col_right_of_wall >= 0) {
178 			check_bumped_look_left();
179 		}
180 #endif // FIX_TWO_COLL_BUG
181 
182 	}
183 }
184 
185 // seg004:02D2
check_bumped_look_left()186 void __pascal far check_bumped_look_left() {
187 	if ((Char.sword == sword_2_drawn || Char.direction < dir_0_right) && // looking left
188 		is_obstacle_at_col(bump_col_right_of_wall)
189 	) {
190 		bumped(get_right_wall_xpos(curr_room, tile_col, tile_row) - char_x_left_coll, dir_0_right);
191 	}
192 }
193 
194 // seg004:030A
check_bumped_look_right()195 void __pascal far check_bumped_look_right() {
196 	if ((Char.sword == sword_2_drawn || Char.direction == dir_0_right) && // looking right
197 		is_obstacle_at_col(bump_col_left_of_wall)
198 	) {
199 		bumped(get_left_wall_xpos(curr_room, tile_col, tile_row) - char_x_right_coll, dir_FF_left);
200 	}
201 }
202 
203 // seg004:0343
is_obstacle_at_col(int tile_col)204 int __pascal far is_obstacle_at_col(int tile_col) {
205 	short tile_row;
206 	tile_row = Char.curr_row;
207 	if (tile_row < 0) {
208 		tile_row += 3;
209 	}
210 	if (tile_row >= 3) {
211 		tile_row -= 3;
212 	}
213 	get_tile(curr_row_coll_room[tile_col], tile_col, tile_row);
214 	return is_obstacle();
215 }
216 
217 // seg004:037E
is_obstacle()218 int __pascal far is_obstacle() {
219 	if (curr_tile2 == tiles_10_potion) {
220 		return 0;
221 	} else if (curr_tile2 == tiles_4_gate) {
222 		if (! can_bump_into_gate()) return 0;
223 	} else if (curr_tile2 == tiles_18_chomper) {
224 		// is the chomper closed?
225 		if (curr_room_modif[curr_tilepos] != 2) return 0;
226 	} else if (
227 		curr_tile2 == tiles_13_mirror &&
228 		Char.charid == charid_0_kid &&
229 		Char.frame >= frame_39_start_run_jump_6 && Char.frame < frame_44_running_jump_5 && // run-jump
230 		Char.direction < dir_0_right // right-to-left only
231 	) {
232 		curr_room_modif[curr_tilepos] = 0x56; // broken mirror or what?
233 		jumped_through_mirror = -1;
234 		return 0;
235 	}
236 	coll_tile_left_xpos = xpos_in_drawn_room(x_bump[tile_col + 5]) + 7;
237 	return 1;
238 }
239 
240 // seg004:0405
xpos_in_drawn_room(int xpos)241 int __pascal far xpos_in_drawn_room(int xpos) {
242 	if (curr_room != drawn_room) {
243 		if (curr_room == room_L || curr_room == room_BL) {
244 			xpos -= 140;
245 		} else if (curr_room == room_R || curr_room == room_BR) {
246 			xpos += 140;
247 		}
248 	}
249 	return xpos;
250 }
251 
252 // seg004:0448
bumped(sbyte delta_x,sbyte push_direction)253 void __pascal far bumped(sbyte delta_x,sbyte push_direction) {
254 	// frame 177: spiked
255 	if (Char.alive < 0 && Char.frame != frame_177_spiked) {
256 		Char.x += delta_x;
257 		if (push_direction < dir_0_right) {
258 			// pushing left
259 			if (curr_tile2 == tiles_20_wall) {
260 				get_tile(curr_room, --tile_col, tile_row);
261 			}
262 		} else {
263 			// pushing right
264 			if (curr_tile2 == tiles_12_doortop ||
265 				curr_tile2 == tiles_7_doortop_with_floor ||
266 				curr_tile2 == tiles_20_wall
267 			) {
268 				++tile_col;
269 				if (curr_room == 0 && tile_col == 10) {
270 					curr_room = Char.room;
271 					tile_col = 0;
272 				}
273 				get_tile(curr_room, tile_col, tile_row);
274 			}
275 		}
276 		if (tile_is_floor(curr_tile2)) {
277 			bumped_floor(push_direction);
278 		} else {
279 			bumped_fall();
280 		}
281 	}
282 }
283 
284 // seg004:04E4
bumped_fall()285 void __pascal far bumped_fall() {
286 	short action;
287 	action = Char.action;
288 	Char.x = char_dx_forward(-4);
289 	if (action == actions_4_in_freefall) {
290 		Char.fall_x = 0;
291 	} else {
292 		seqtbl_offset_char(seq_45_bumpfall); // fall after bumped
293 		play_seq();
294 	}
295 	bumped_sound();
296 }
297 
298 // seg004:0520
bumped_floor(sbyte push_direction)299 void __pascal far bumped_floor(sbyte push_direction) {
300 	short frame;
301 	short seq_index;
302 	if (Char.sword != sword_2_drawn && (word)(y_land[Char.curr_row + 1] - Char.y) >= (word)15) {
303 		bumped_fall();
304 	} else {
305 		Char.y = y_land[Char.curr_row + 1];
306 		if (Char.fall_y >= 22) {
307 			Char.x = char_dx_forward(-5);
308 		} else {
309 			Char.fall_y = 0;
310 			if (Char.alive) {
311 				if (Char.sword == sword_2_drawn) {
312 					if (push_direction == Char.direction) {
313 						seqtbl_offset_char(seq_65_bump_forward_with_sword); // pushed forward with sword (Kid)
314 						play_seq();
315 						Char.x = char_dx_forward(1);
316 						return;
317 					} else {
318 						seq_index = seq_64_pushed_back_with_sword; // pushed back with sword
319 					}
320 				} else {
321 					frame = Char.frame;
322 					if (frame == 24 || frame == 25 ||
323 						(frame >= 40 && frame < 43) ||
324 						(frame >= frame_102_start_fall_1 && frame < 107)
325 					) {
326 						seq_index = seq_46_hardbump; // bump into wall after run-jump (crouch)
327 					} else {
328 						seq_index = seq_47_bump; // bump into wall
329 					}
330 				}
331 				seqtbl_offset_char(seq_index);
332 				play_seq();
333 				bumped_sound();
334 			}
335 		}
336 	}
337 }
338 
339 // seg004:05F1
bumped_sound()340 void __pascal far bumped_sound() {
341 	is_guard_notice = 1;
342 	play_sound(sound_8_bumped); // touching a wall
343 }
344 
345 // seg004:0601
clear_coll_rooms()346 void __pascal far clear_coll_rooms() {
347 	memset_near(prev_coll_room, -1, sizeof(prev_coll_room));
348 	memset_near(curr_row_coll_room, -1, sizeof(curr_row_coll_room));
349 	memset_near(below_row_coll_room, -1, sizeof(below_row_coll_room));
350 	memset_near(above_row_coll_room, -1, sizeof(above_row_coll_room));
351 #ifdef FIX_COLL_FLAGS
352 	// workaround
353 	memset_near(prev_coll_flags, 0, sizeof(prev_coll_flags));
354 	memset_near(curr_row_coll_flags, 0, sizeof(curr_row_coll_flags));
355 	memset_near(below_row_coll_flags, 0, sizeof(below_row_coll_flags));
356 	memset_near(above_row_coll_flags, 0, sizeof(above_row_coll_flags));
357 #endif
358 	prev_collision_row = -1;
359 }
360 
361 // seg004:0657
can_bump_into_gate()362 int __pascal far can_bump_into_gate() {
363 	return (curr_room_modif[curr_tilepos] >> 2) + 6 < char_height;
364 }
365 
366 // seg004:067C
get_edge_distance()367 int __pascal far get_edge_distance() {
368 /*
369 Possible results in edge_type:
370 0: closer/sword/potion
371 1: edge
372 2: floor (nothing near char)
373 */
374 	short distance;
375 	byte tiletype;
376 	determine_col();
377 	load_frame_to_obj();
378 	set_char_collision();
379 	tiletype = get_tile_at_char();
380 	if (wall_type(tiletype) != 0) {
381 		tile_col = Char.curr_col;
382 		distance = dist_from_wall_forward(tiletype);
383 		if (distance >= 0) {
384 			loc_59DD:
385 			if (distance < 14) {
386 				edge_type = 1;
387 			} else {
388 				edge_type = 2;
389 				distance = 11;
390 			}
391 		} else {
392 			goto loc_59E8;
393 		}
394 	} else {
395 		loc_59E8:
396 		tiletype = get_tile_infrontof_char();
397 		if (tiletype == tiles_12_doortop && Char.direction >= dir_0_right) {
398 			loc_59FB:
399 			edge_type = 0;
400 			distance = distance_to_edge_weight();
401 		} else {
402 			if (wall_type(tiletype) != 0) {
403 				tile_col = infrontx;
404 				distance = dist_from_wall_forward(tiletype);
405 				if (distance >= 0) goto loc_59DD;
406 			}
407 			if (tiletype == tiles_11_loose) goto loc_59FB;
408 			if (
409 				tiletype == tiles_6_closer ||
410 				tiletype == tiles_22_sword ||
411 				tiletype == tiles_10_potion
412 			) {
413 				distance = distance_to_edge_weight();
414 				if (distance != 0) {
415 					edge_type = 0;
416 				} else {
417 					edge_type = 2;
418 					distance = 11;
419 				}
420 			} else {
421 				if (tile_is_floor(tiletype)) {
422 					edge_type = 2;
423 					distance = 11;
424 				} else {
425 					goto loc_59FB;
426 				}
427 			}
428 		}
429 	}
430 	curr_tile2 = tiletype;
431 	return distance;
432 }
433 
434 // seg004:076B
check_chomped_kid()435 void __pascal far check_chomped_kid() {
436 	short tile_col;
437 	short tile_row;
438 	tile_row = Char.curr_row;
439 	for (tile_col = 0; tile_col < 10; ++tile_col) {
440 		if (curr_row_coll_flags[tile_col] == 0xFF &&
441 			get_tile(curr_row_coll_room[tile_col], tile_col, tile_row) == tiles_18_chomper &&
442 			(curr_room_modif[curr_tilepos] & 0x7F) == 2 // closed chomper
443 		) {
444 			chomped();
445 		}
446 	}
447 }
448 
449 // seg004:07BF
chomped()450 void __pascal far chomped() {
451 	#ifdef FIX_SKELETON_CHOMPER_BLOOD
452 	if (!(fixes->fix_skeleton_chomper_blood && Char.charid == charid_4_skeleton))
453 	#endif
454 		curr_room_modif[curr_tilepos] |= 0x80; // put blood
455 	if (Char.frame != frame_178_chomped && Char.room == curr_room) {
456 		#ifdef FIX_OFFSCREEN_GUARDS_DISAPPEARING
457 		// a guard can get teleported to the other side of kid's room
458 		// when hitting a chomper in another room
459 		if (fixes->fix_offscreen_guards_disappearing) {
460 			short chomper_col = tile_col;
461 			if (curr_room != Char.room)	{
462 				if (curr_room == level.roomlinks[Char.room - 1].right) {
463 					chomper_col += 10;
464 				} else if (curr_room == level.roomlinks[Char.room - 1].left) {
465 					chomper_col -= 10;
466 				}
467 			}
468 			Char.x = x_bump[chomper_col + 5] + 7;
469 		} else {
470 		#endif
471 			Char.x = x_bump[tile_col + 5] + 7;
472 		#ifdef FIX_OFFSCREEN_GUARDS_DISAPPEARING
473 		}
474 		#endif
475 		Char.x = char_dx_forward(7 - !Char.direction);
476 		Char.y = y_land[Char.curr_row + 1];
477 		take_hp(100);
478 		play_sound(sound_46_chomped); // something chomped
479 		seqtbl_offset_char(seq_54_chomped); // chomped
480 		play_seq();
481 	}
482 }
483 
484 // seg004:0833
check_gate_push()485 void __pascal far check_gate_push() {
486 	// Closing gate pushes Kid
487 	short frame;
488 	short orig_col;
489 	frame = Char.frame;
490 	if (Char.action == actions_7_turn ||
491 		frame == frame_15_stand || // stand
492 		(frame >= frame_108_fall_land_2 && frame < 111) // crouch
493 	) {
494 		get_tile_at_char();
495 		orig_col = tile_col;
496 		int orig_room = curr_room;
497 		if ((curr_tile2 == tiles_4_gate ||
498 			get_tile(curr_room, --tile_col, tile_row) == tiles_4_gate) &&
499 			(curr_row_coll_flags[tile_col] & prev_coll_flags[tile_col]) == 0xFF &&
500 			can_bump_into_gate()
501 		) {
502 			bumped_sound();
503 #ifdef FIX_CAPED_PRINCE_SLIDING_THROUGH_GATE
504 			if (fixes->fix_caped_prince_sliding_through_gate) {
505 				// If get_tile() changed curr_room from orig_room to the left neighbor of orig_room (because tile_col was outside room orig_room),
506 				// then change tile_col (and curr_room) so that orig_col and tile_col are meant in the same room.
507 				if (curr_room == level.roomlinks[orig_room - 1].left) {
508 					tile_col -= 10;
509 					curr_room = orig_room;
510 				}
511 			}
512 #endif
513 			//printf("check_gate_push: orig_col = %d, tile_col = %d, curr_room = %d, Char.room = %d, orig_room = %d\n", orig_col, tile_col, curr_room, Char.room, orig_room);
514 			// push Kid left if orig_col <= tile_col, gate at char's tile
515 			// push Kid right if orig_col > tile_col, gate is left from char's tile
516 			Char.x += 5 - (orig_col <= tile_col) * 10;
517 		}
518 	}
519 }
520 
521 // seg004:08C3
check_guard_bumped()522 void __pascal far check_guard_bumped() {
523 	if (
524 		Char.action == actions_1_run_jump &&
525 		Char.alive < 0 &&
526 		Char.sword >= sword_2_drawn
527 	) {
528 		if (
529 
530 			#ifdef FIX_PUSH_GUARD_INTO_WALL
531 			// Should also check for a wall BEHIND the guard, instead of only the current tile
532 			(fixes->fix_push_guard_into_wall && get_tile_behind_char() == tiles_20_wall) ||
533 			#endif
534 
535 			get_tile_at_char() == tiles_20_wall ||
536 			curr_tile2 == tiles_7_doortop_with_floor ||
537 			(curr_tile2 == tiles_4_gate && can_bump_into_gate()) ||
538 			(Char.direction >= dir_0_right && (
539 				get_tile(curr_room, --tile_col, tile_row) == tiles_7_doortop_with_floor ||
540 				(curr_tile2 == tiles_4_gate && can_bump_into_gate())
541 			))
542 		) {
543 			load_frame_to_obj();
544 			set_char_collision();
545 			if (is_obstacle()) {
546 				short delta_x;
547 				delta_x = dist_from_wall_behind(curr_tile2);
548 				if (delta_x < 0 && delta_x > -13) {
549 					Char.x = char_dx_forward(-delta_x);
550 					seqtbl_offset_char(seq_65_bump_forward_with_sword); // pushed to wall with sword (Guard)
551 					play_seq();
552 					load_fram_det_col();
553 				}
554 			}
555 		}
556 	}
557 }
558 
559 // seg004:0989
check_chomped_guard()560 void __pascal far check_chomped_guard() {
561 	get_tile_at_char();
562 	if ( ! check_chomped_here()) {
563 		get_tile(curr_room, ++tile_col, tile_row);
564 		check_chomped_here();
565 	}
566 }
567 
568 // seg004:09B0
check_chomped_here()569 int __pascal far check_chomped_here() {
570 	if (curr_tile2 == tiles_18_chomper &&
571 		(curr_room_modif[curr_tilepos] & 0x7F) == 2
572 	) {
573 		coll_tile_left_xpos = x_bump[tile_col + 5] + 7;
574 		if (get_left_wall_xpos(curr_room, tile_col, tile_row) < char_x_right_coll &&
575 			get_right_wall_xpos(curr_room, tile_col, tile_row) > char_x_left_coll
576 		) {
577 			chomped();
578 			return 1;
579 		} else {
580 			return 0;
581 		}
582 	} else {
583 		return 0;
584 	}
585 }
586 
587 // seg004:0A10
dist_from_wall_forward(byte tiletype)588 int __pascal far dist_from_wall_forward(byte tiletype) {
589 	short type;
590 	if (tiletype == tiles_4_gate && ! can_bump_into_gate()) {
591 		return -1;
592 	} else {
593 		coll_tile_left_xpos = x_bump[tile_col + 5] + 7;
594 		type = wall_type(tiletype);
595 		if (type == 0) return -1;
596 		if (Char.direction < dir_0_right) {
597 			// looking left
598 			//return wall_dist_from_right[type] + char_x_left_coll - coll_tile_left_xpos - 13;
599 			return char_x_left_coll - (coll_tile_left_xpos + 13 - wall_dist_from_right[type]);
600 		} else {
601 			// looking right
602 			return wall_dist_from_left[type] + coll_tile_left_xpos - char_x_right_coll;
603 		}
604 	}
605 }
606 
607 // seg004:0A7B
dist_from_wall_behind(byte tiletype)608 int __pascal far dist_from_wall_behind(byte tiletype) {
609 	short type;
610 	type = wall_type(tiletype);
611 	if (type == 0) {
612 		return 99;
613 	} else {
614 		if (Char.direction >= dir_0_right) {
615 			// looking right
616 			//return wall_dist_from_right[type] + char_x_left_coll - coll_tile_left_xpos - 13;
617 			return char_x_left_coll - (coll_tile_left_xpos + 13 - wall_dist_from_right[type]);
618 		} else {
619 			// looking left
620 			return wall_dist_from_left[type] + coll_tile_left_xpos - char_x_right_coll;
621 		}
622 	}
623 }
624