1 #include <stdlib.h>
2 #include <math.h>
3 #include <string.h>
4 #include "draw_scene.h"
5 #include "bbox_tree.h"
6 #include "cal.h"
7 #include "console.h"
8 #include "cursors.h"
9 #include "elconfig.h"
10 #if !defined(MAP_EDITOR)
11 #include "elwindows.h"
12 #endif
13 #include "events.h"
14 #include "eye_candy_wrapper.h"
15 #include "gamewin.h"
16 #include "gl_init.h"
17 #include "hud.h"
18 #include "hud_timer.h"
19 #include "interface.h"
20 #include "items.h"
21 #include "main.h"
22 #include "map.h"
23 #include "multiplayer.h"
24 #include "new_actors.h"
25 #include "new_character.h"
26 #include "pm_log.h"
27 #include "shadows.h"
28 #include "skeletons.h"
29 #include "sky.h"
30 #include "spells.h"
31 #include "sound.h"
32 #include "storage.h"
33 #include "tiles.h"
34 #include "weather.h"
35 
36 static char have_display = 0;
37 
38 float camera_x=0;
39 float camera_y=0;
40 float camera_z=0;
41 float rx=-60;
42 float ry=0;
43 float rz=45;
44 float terrain_scale=2.0f;
45 float zoom_level=3.0f;
46 #define MAX(a,b) ( ((a)>(b)) ? (a):(b))
47 //First Person Camera mode state
48 int first_person = 0;
49 float old_rx=-60;
50 float old_rz=45;
51 float old_zoom_level=3.0;
52 float max_zoom_level=4.0f;
53 
54 float fine_camera_rotation_speed;
55 float normal_camera_rotation_speed;
56 
57 float camera_rotation_speed;
58 int camera_rotation_duration;
59 
60 float camera_tilt_speed;
61 int camera_tilt_duration;
62 
63 float normal_camera_deceleration = 0.2;
64 float camera_rotation_deceleration;
65 float camera_tilt_deceleration;
66 
67 double camera_x_speed;
68 int camera_x_duration;
69 
70 double camera_y_speed;
71 int camera_y_duration;
72 
73 double camera_z_speed;
74 int camera_z_duration;
75 
76 int camera_zoom_dir;
77 int camera_zoom_duration=0;
78 int camera_zoom_speed=1;
79 
80 float new_zoom_level=3.0f;
81 float camera_distance = 2.5f;
82 
83 int reset_camera_at_next_update = 1;
84 
85 //Follow camera state stuff
86 int fol_cam = 1;	       // follow camera state (on/off)
87 int fol_cam_behind = 0;    // keep the camera behind the char
88 float camera_kludge = 0.0; // the direction player is facing
89 float last_kludge = 0.0;   // how far the camera deviated from camera_kludge
90 float fol_strn = 0.1;      // follow camera response strength
91 float fol_con = 7.0;       // follow camera constant speed
92 float fol_lin = 1.0;       // follow camera linear deceleration
93 float fol_quad = 1.0;      // follow camera quadratic deceleration
94 int ext_cam = 1;	       // extended camera state (on/off)
95 int ext_cam_auto_zoom = 0; // auto zooming state for extended camera (on/off)
96 float min_tilt_angle = 30.0; // minimum tilt angle for the extended camera
97 float max_tilt_angle = 90.0; // maximum tilt angle for the extended camera
98 float hold_camera = 0.0;   // backup of the rz value before kludge is applied
99 
100 int last_texture=-2;
101 int cons_text;
102 int icons_text;
103 
104 int ground_detail_text;
105 
106 float clouds_movement_u=-8;
107 float clouds_movement_v=-3;
108 Uint32 last_clear_clouds=0;
109 
110 GLenum base_unit=GL_TEXTURE0_ARB,detail_unit=GL_TEXTURE1_ARB,shadow_unit=GL_TEXTURE2_ARB,extra_unit=GL_TEXTURE3_ARB,normal_map_unit=GL_TEXTURE4_ARB;
111 
112 Uint32 draw_delay = 0;
113 
114 
draw_scene()115 void draw_scene()
116 {
117 	CHECK_GL_ERRORS();
118 
119 	glClearColor(skybox_fog_color[0], skybox_fog_color[1], skybox_fog_color[2], 0.0);
120 
121 	if(!shadows_on || !have_stencil)glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
122 	else glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
123 
124 	if (!have_display)
125 	{
126 		// No scrolling when switching modes...
127 		new_zoom_level = zoom_level;
128 		// Hide the moveable hud windows if they are not on the bottom or side hud bar
129 		hide_moved_hud_windows();
130 	}
131 
132 	glLoadIdentity ();	// Reset The Matrix
133 
134 	Enter2DMode ();
135 	display_windows (1);
136 
137 	// Have to draw the dragged item *after* all windows
138 
139 	glColor3f(1.0f,1.0f,1.0f);
140 	if (item_dragged != -1)
141 		drag_item (item_dragged, 0, 0);
142 	else if (use_item != -1 && current_cursor == CURSOR_USE_WITEM)
143 		drag_item (use_item, 0, ((cursor_scale_factor > 1) ?0: 1));
144 	else if (storage_item_dragged != -1)
145 		drag_item (storage_item_dragged, 1, 0);
146 	draw_special_cursors();
147 
148 	Leave2DMode ();
149 
150 	if(elwin_mouse >= 0)
151 	{
152 		if (current_cursor != elwin_mouse) change_cursor(elwin_mouse);
153 		elwin_mouse = -1;
154 	}
155 
156 	SDL_GL_SwapWindow(el_gl_window);
157 	CHECK_GL_ERRORS();
158 
159 	/* stuff to do not every frame, twice a second is fine */
160 	{
161 		static Uint32 last_half_second_timer = 0;
162 		static int first_time = 1;
163 		Uint32 current_time = SDL_GetTicks();
164 		if (first_time)
165 		{
166 			last_half_second_timer = current_time;
167 			first_time = 0;
168 		}
169 		if ((current_time - last_half_second_timer) > 500u)
170 		{
171 			/* start or stop the harvesting effect depending on harvesting state */
172 			check_harvesting_effect();
173 			/* check for and possibly do auto save */
174 			auto_save_local_and_server();
175 			/* action on afk state changes */
176 			check_afk_state();
177 			/* the timer in the hud */
178 			update_hud_timer();
179 			/* check if we need to do buff duration requests */
180 			check_then_do_buff_duration_request();
181 			/* check if we are doing a server connection test */
182 			check_if_testing_server_connection();
183 			/* check if used item counter confirmation has expired */
184 			used_item_counter_timer();
185 			/* make sure minimised or restored window is noticed */
186 			check_minimised_or_restore_window();
187 			/* check if we need to action a scale change for the config window */
188 			check_for_config_window_scale();
189 			/* until next time */
190 			last_half_second_timer = current_time;
191 		}
192 	}
193 
194 	if (draw_delay > 0)
195 	{
196 		SDL_Delay (draw_delay);
197 		draw_delay = 0;
198 	}
199 }
200 
move_camera()201 void move_camera ()
202 {
203 	float x, y, z;
204 	// float head_pos[3];
205 	float follow_speed;
206 	actor *me = get_our_actor ();
207 
208     if(!me){
209 		return;
210 	}
211 
212 	x = (float)me->x_pos+0.25f;
213 	y = (float)me->y_pos+0.25f;
214 
215     // cal_get_actor_bone_local_position(me, get_actor_bone_id(me, head_bone), NULL, head_pos);
216 
217     /* Schmurk: I've commented this out because I don't see why the position of
218      * the camera should be different from the head position in ext cam and fpv */
219 /* 	if (first_person){ */
220 /* 		z = (ext_cam?-1.7f:-2.1f) + height_map[me->y_tile_pos*tile_map_size_x*6+me->x_tile_pos]*0.2f + head_pos[2]; */
221 /* 	} else if (ext_cam){ */
222 /* 		z = -1.6f + height_map[me->y_tile_pos*tile_map_size_x*6+me->x_tile_pos]*0.2f + head_pos[2]; */
223 	if (first_person || ext_cam) {
224         // the camera position corresponds to the head position
225 		z = get_tile_height(me->x_tile_pos, me->y_tile_pos);
226 		// z += (head_pos[2]+0.1)*get_actor_scale(me);
227 
228 		//attachment_props *att_props = get_attachment_props_if_held(me);
229 		//z += (me->sitting ? 0.7 : 1.5) * get_actor_scale(me);
230 		if (me->attached_actor>=0) z+=me->z_pos + me->attachment_shift[Z]+2.0*get_actor_scale(me);
231 		else z += (me->sitting ? 0.7 : 1.5) * get_actor_scale(me);
232 	} else {
233 		z = get_tile_height(me->x_tile_pos, me->y_tile_pos) + sitting;
234 	}
235 
236 	if(first_person||ext_cam){
237 		follow_speed = 150.0f;
238 	} else {
239 		follow_speed = 300.0f;
240 	}
241 	if(reset_camera_at_next_update){
242 		camera_x = -x;
243 		camera_y = -y;
244 		camera_z = -z;
245 		camera_x_duration=0;
246 		camera_y_duration=0;
247 		camera_z_duration=0;
248         reset_camera_at_next_update = 0;
249 		set_all_intersect_update_needed(main_bbox_tree);
250 	} else {
251 		//move near the actor, but smoothly
252 		camera_x_speed=(x+camera_x)/follow_speed;
253 		camera_x_duration=follow_speed;
254 		camera_y_speed=(y+camera_y)/follow_speed;
255 		camera_y_duration=follow_speed;
256 		camera_z_speed=(z+camera_z)/follow_speed;
257 		camera_z_duration=follow_speed;
258 	}
259 
260 
261 	if (first_person){
262 		// glTranslatef(head_pos[0], head_pos[1], 0.0);
263 	} else {
264 		glTranslatef(0.0f, 0.0f, -zoom_level*camera_distance);
265 	}
266 
267 	glRotatef(rx, 1.0f, 0.0f, 0.0f);
268 	glRotatef(rz, 0.0f, 0.0f, 1.0f);
269 	glTranslatef(camera_x, camera_y, camera_z);
270 }
271 
272 
273 
clamp_camera(void)274 void clamp_camera(void)
275 {
276 		if(first_person){
277 			if(rx < -170){
278 				rx = -170;
279 				camera_tilt_duration=0;
280 				camera_tilt_speed = 0.0;
281 			} else if(rx > -30){
282 				rx = -30;
283 				camera_tilt_duration=0;
284 				camera_tilt_speed = 0.0;
285 			}
286 		} else if(ext_cam){
287 			if(rx < -max_tilt_angle){
288 				rx = -max_tilt_angle;
289 				camera_tilt_duration=0;
290 				camera_tilt_speed = 0.0;
291 			} else if(rx > -min_tilt_angle){
292 				rx = -min_tilt_angle;
293 				camera_tilt_duration=0;
294 				camera_tilt_speed = 0.0;
295 			}
296 	} else {
297 		if(rx < -60){
298 			rx = -60;
299 			camera_tilt_duration=0;
300 			camera_tilt_speed = 0.0;
301 		} else if(rx > -45){
302 			rx = -45;
303 			camera_tilt_duration=0;
304 			camera_tilt_speed = 0.0;
305 		}
306 	}
307 	if (have_mouse){
308 		camera_rotation_duration = 0;
309 		camera_tilt_duration=0;
310 		camera_rotation_speed = 0.0;
311 		camera_tilt_speed = 0.0;
312 	}
313 	if(rz > 360) {
314 		rz -= 360;
315 	} else if (rz < 0) {
316 		rz += 360;
317 	}
318 	if(new_zoom_level > max_zoom_level){
319 		new_zoom_level = max_zoom_level;
320 		camera_zoom_duration = 0;
321 	} else if(new_zoom_level < 0.3f) {
322 		new_zoom_level = 0.3f;
323 		camera_zoom_duration = 0;
324 	}
325 }
326 
327 
328 
329 int adjust_view;
330 
update_camera()331 void update_camera()
332 {
333 	const float c_delta = 0.1f;
334 
335 	static int last_update = 0;
336 	int time_diff = cur_time - last_update;
337 
338 	static float old_camera_x = 0;
339 	static float old_camera_y = 0;
340 	static float old_camera_z = 0;
341 	float adjust;
342 	actor *me = get_our_actor();
343 
344 	old_rx=rx;
345 	old_rz=rz;
346 	new_zoom_level=old_zoom_level=zoom_level;
347 
348 	//printf("kludge: %f, hold: %f, rx: %f, rz %f, zoom: %f\n",camera_kludge, hold_camera,rx,rz,zoom_level);
349 
350 	if (fol_cam && !fol_cam_behind)
351 		rz = hold_camera;
352 	if (me)
353 		camera_kludge = -me->z_rot;
354 
355 	/* This is a BIG hack to not polluate the code but if this feature
356 	 * is accepted and the flag is removed, all the code that
357 	 * follows will have to be changed in order to get rid of
358 	 * camera_rotation_duration and camera_tilt_duration. */
359 	camera_rotation_duration = camera_rotation_speed != 0.0 ? time_diff : 0.0;
360 	camera_tilt_duration = camera_tilt_speed != 0.0 ? time_diff : 0.0;
361 
362 	if(camera_rotation_duration > 0){
363 		if (time_diff <= camera_rotation_duration)
364 			rz+=camera_rotation_speed*time_diff;
365 		else
366 			rz+=camera_rotation_speed*camera_rotation_duration;
367 		camera_rotation_duration-=time_diff;
368 		adjust_view++;
369 	}
370 	if(camera_x_duration > 0){
371 		if(camera_x_speed>1E-4 || camera_x_speed<-1E-4){
372 			if (time_diff <= camera_x_duration)
373 				camera_x-=camera_x_speed*time_diff;
374 			else
375 				camera_x-=camera_x_speed*camera_x_duration;
376 			if(fabs(camera_x-old_camera_x) >= c_delta){
377 				adjust_view++;
378 			}
379 		}
380 		camera_x_duration-=time_diff;
381 	}
382 	if(camera_y_duration > 0){
383 		if(camera_y_speed>1E-4 || camera_y_speed<-1E-4){
384 			if (time_diff <= camera_y_duration)
385 				camera_y-=camera_y_speed*time_diff;
386 			else
387 				camera_y-=camera_y_speed*camera_y_duration;
388 			if(fabs(camera_y-old_camera_y) >= c_delta){
389 				adjust_view++;
390 			}
391 		}
392 		camera_y_duration-=time_diff;
393 	}
394 	if(camera_z_duration > 0){
395 		if(camera_z_speed>1E-4 || camera_z_speed<-1E-4){
396 			if (time_diff <= camera_z_duration)
397 				camera_z-=camera_z_speed*time_diff;
398 			else
399 				camera_z-=camera_z_speed*camera_z_duration;
400 			if(fabs(camera_z-old_camera_z) >= c_delta){
401 				adjust_view++;
402 			}
403 		}
404 		camera_z_duration-=time_diff;
405 	}
406 
407 	if(camera_tilt_duration > 0) {
408 		if (time_diff <= camera_tilt_duration)
409 			rx+=camera_tilt_speed*time_diff;
410 		else
411 			rx+=camera_tilt_speed*camera_tilt_duration;
412 		camera_tilt_duration-=time_diff;
413 		adjust_view++;
414 	}
415 	if(camera_zoom_duration > 0) {
416 		if (time_diff <= camera_zoom_duration)
417 			new_zoom_level += camera_zoom_speed*(camera_zoom_dir==1?0.003f:-0.003f)*time_diff;
418 		else
419 			new_zoom_level += camera_zoom_speed*(camera_zoom_dir==1?0.003f:-0.003f)*camera_zoom_duration;
420 		camera_zoom_duration-=time_diff;
421 		adjust_view++;
422 	}
423 	else
424 		camera_zoom_speed = 1;
425 
426 
427 	if (camera_rotation_speed > 0.0)
428 	{
429 		camera_rotation_speed -= time_diff * camera_rotation_deceleration;
430 		if (camera_rotation_speed < 0.0)
431 			camera_rotation_speed = 0.0;
432 	}
433 	else if (camera_rotation_speed < 0.0)
434 	{
435 		camera_rotation_speed += time_diff * camera_rotation_deceleration;
436 		if (camera_rotation_speed > 0.0)
437 			camera_rotation_speed = 0.0;
438 	}
439 	if (camera_tilt_speed > 0.0)
440 	{
441 		camera_tilt_speed -= time_diff * camera_tilt_deceleration;
442 		if (camera_tilt_speed < 0.0)
443 			camera_tilt_speed = 0.0;
444 	}
445 	else if (camera_tilt_speed < 0.0)
446 	{
447 		camera_tilt_speed += time_diff * camera_tilt_deceleration;
448 		if (camera_tilt_speed > 0.0)
449 			camera_tilt_speed = 0.0;
450 	}
451 
452 	clamp_camera();
453 
454 	if (ext_cam && !first_person && me &&
455 		rx <= -min_tilt_angle && rx >= -max_tilt_angle)
456 	{
457 		float rot_x[9], rot_z[9], rot[9], dir[3];
458 		float vect[3] = {0.0, 0.0, new_zoom_level*camera_distance};
459 		int tx, ty;
460 		float tz;
461 
462 		// we compute the camera position
463 		MAT3_ROT_X(rot_x, -rx*M_PI/180.0);
464 		MAT3_ROT_Z(rot_z, -rz*M_PI/180.0);
465 		MAT3_MULT(rot, rot_z, rot_x);
466 		MAT3_VECT3_MULT(dir, rot, vect);
467 
468 		// we take the tile where the camera is
469 		tx = (int)((dir[0] - camera_x)*2);
470 		ty = (int)((dir[1] - camera_y)*2);
471 
472 		if (get_tile_walkable(tx, ty))
473 		{
474 			tz = get_tile_height(tx, ty);
475 		}
476 		else
477 		{
478 			// if the tile is outside the map, we take the height at the actor position
479 			tz = get_tile_height(me->x_tile_pos, me->y_tile_pos);
480 		}
481 		// here we use a shift of 0.2 to avoid to be too close to the ground
482 		if (tz + 0.2 > dir[2] - camera_z)
483 		{
484 			if (ext_cam_auto_zoom) // new behaviour
485 			{
486 				// if the camera is under the ground, we change the zoom level
487 				if (fabsf(dir[2]) > 1E-4)
488 					new_zoom_level *= (tz + camera_z + 0.2) / dir[2];
489 				else
490 					new_zoom_level = 0.0;
491 
492 				if (new_zoom_level < 1.0)
493 				{
494 					new_zoom_level = 1.0;
495 					camera_tilt_duration = camera_zoom_duration = 0;
496 					camera_tilt_speed = 0.0;
497 					if (fabsf(tz + camera_z + 0.2f) < fabsf(vect[2]) - 0.01)
498 						rx = -90.0 + 180.0 * asinf((tz + camera_z + 0.2) / vect[2]) / M_PI;
499 				}
500 				else if (new_zoom_level > old_zoom_level)
501 				{
502 					new_zoom_level = old_zoom_level;
503 					camera_tilt_duration = camera_zoom_duration = 0;
504 					camera_tilt_speed = 0.0;
505 				}
506 			}
507 			else // old freecam behaviour
508 			{
509 				new_zoom_level = old_zoom_level;
510 				camera_tilt_duration = camera_zoom_duration = 0;
511 				camera_tilt_speed = 0.0;
512 				if (fabsf(tz + camera_z + 0.2f) < fabsf(vect[2]) - 0.01)
513 					rx = -90.0 + 180.0 * asinf((tz + camera_z + 0.2) / vect[2]) / M_PI;
514 			}
515 		}
516 	}
517 
518 	if(adjust_view){
519 		set_all_intersect_update_needed(main_bbox_tree);
520 		old_camera_x= camera_x;
521 		old_camera_y= camera_y;
522 		old_camera_z= camera_z;
523 	}
524 
525 
526 	hold_camera = rz;
527 	if (fol_cam) {
528 		static int fol_cam_stop = 0;
529 
530 		if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) || camera_rotation_speed != 0)
531 			fol_cam_stop = 1;
532 		else if (me && me->moving && fol_cam_stop)
533 			fol_cam_stop = 0;
534 
535 		if (last_kludge != camera_kludge && !fol_cam_stop) {
536 			set_all_intersect_update_needed(main_bbox_tree);
537 			adjust = (camera_kludge-last_kludge);
538 
539 			//without this the camera will zip the wrong way when camera_kludge
540 			//flips from 180 <-> -180
541 			if      (adjust >=  180) adjust -= 360.0;
542 			else if (adjust <= -180) adjust += 360.0;
543 
544 			if (fabs(adjust) < fol_strn) {
545 				last_kludge=camera_kludge;
546 			}
547 			else {
548 				last_kludge += fol_strn*(
549 					adjust*(fol_quad*fol_strn + fol_lin)+
550 					fol_con*(adjust>0?1:-1))/
551 					(fol_quad+fol_lin+fol_con+.000001f);//cheap no/0
552 			}
553 		}
554 		if (fol_cam_behind)
555         {
556             if (!fol_cam_stop)
557                 rz = -last_kludge;
558             else
559                 last_kludge = -rz;
560         }
561 		else
562 			rz -= last_kludge;
563 	}
564 
565 	//Make Character Turn with Camera
566 	if (have_mouse && !on_the_move (get_our_actor ()))
567 	{
568 		adjust = rz;
569 		//without this the character will turn the wrong way when camera_kludge
570 		//and character are in certain positions
571 		if      (adjust >=  180) adjust -= 360.0;
572 		else if (adjust <= -180) adjust += 360.0;
573 		adjust+=camera_kludge;
574 		if      (adjust >=  180) adjust -= 360.0;
575 		else if (adjust <= -180) adjust += 360.0;
576 		if (adjust > 35){
577 			Uint8 str[2];
578 			str[0] = TURN_LEFT;
579 			my_tcp_send (my_socket, str, 1);
580 		} else if (adjust < -35){
581 			Uint8 str[2];
582 			str[0] = TURN_RIGHT;
583 			my_tcp_send (my_socket, str, 1);
584 		}
585 	}
586 	adjust_view = 0;
587 	last_update = cur_time;
588 }
589 
590 #if !defined(MAP_EDITOR)
update_have_display(window_info * win)591 int update_have_display(window_info * win)
592 {
593 	// if the calling window is shown, we have a display, else check all 3d windows
594 	have_display = (win->displayed || get_show_window(game_root_win) || get_show_window(newchar_root_win));
595 	return 0;
596 }
597 #endif
598