1 #include <stdlib.h>
2 #include <string.h>
3 #include <time.h>
4 #include "actor_scripts.h"
5 #include "actors.h"
6 #include "asc.h"
7 #include "cal.h"
8 #include "cal3d_wrapper.h"
9 #include "counters.h"
10 #include "cursors.h"
11 #include "draw_scene.h"
12 #include "elconfig.h"
13 #include "errors.h"
14 #include "gamewin.h"
15 #include "hud_statsbar_window.h"
16 #include "interface.h"
17 #include "missiles.h"
18 #include "new_actors.h"
19 #include "multiplayer.h"
20 #include "new_character.h"
21 #include "particles.h"
22 #include "pathfinder.h"
23 #include "platform.h"
24 #include "skeletons.h"
25 #include "special_effects.h"
26 #ifdef NEW_SOUND
27 #include "sound.h"
28 #endif // NEW_SOUND
29 #include "spells.h"
30 #include "text.h"
31 #include "tiles.h"
32 #include "timers.h"
33 #include "translate.h"
34 #include "eye_candy_wrapper.h"
35 #include "minimap.h"
36 #include "io/elfilewrapper.h"
37 #include "io/cal3d_io_wrapper.h"
38 #include "actor_init.h"
39 #include "textures.h"
40 
41 #ifndef EXT_ACTOR_DICT
42 const dict_elem skin_color_dict[] =
43 	{ { "brown"	, SKIN_BROWN	},
44 	  { "normal", SKIN_NORMAL	},
45 	  { "pale"	, SKIN_PALE		},
46 	  { "tan"	, SKIN_TAN		},
47 	  { "darkblue", SKIN_DARK_BLUE },	// Elf's only
48 	  { "dark_blue", SKIN_DARK_BLUE },	// Elf's only, synonym
49 	  { "white" , SKIN_WHITE    },		// Draegoni only
50 	  { NULL	, -1			}
51 	};
52 
53 const dict_elem glow_mode_dict[] =
54 	{ { "none"   , GLOW_NONE    },
55 	  { "fire"   , GLOW_FIRE    },
56 	  { "ice"    , GLOW_COLD    },
57 	  { "thermal", GLOW_THERMAL },
58 	  { "magic"  , GLOW_MAGIC   },
59 	  { NULL     , -1           }
60 	};
61 
62 const dict_elem head_number_dict[] =
63 	{ { "1" ,  HEAD_1 },
64 	  { "2" ,  HEAD_2 },
65 	  { "3" ,  HEAD_3 },
66 	  { "4" ,  HEAD_4 },
67 	  { "5" ,  HEAD_5 },
68 	  { NULL, -1      }
69 	};
70 int actor_part_sizes[ACTOR_NUM_PARTS] = {10, 40, 50, 100, 100, 100, 10, 20, 40, 60, 20, 20};		// Elements according to actor_parts_enum
71 #else // EXT_ACTOR_DICT
72 #define MAX_SKIN_COLORS 7
73 #define MAX_GLOW_MODES 5
74 #define MAX_HEAD_NUMBERS 5
75 dict_elem skin_color_dict[MAX_SKIN_COLORS];
76 dict_elem head_number_dict[MAX_GLOW_MODES];
77 dict_elem glow_mode_dict[MAX_HEAD_NUMBERS];
78 int num_skin_colors = 0;
79 int num_head_numbers = 0;
80 int num_glow_modes = 0;
81 int actor_part_sizes[ACTOR_NUM_PARTS];
82 #endif // EXT_ACTOR_DICT
83 
84 //Forward declarations
85 int cal_load_weapon_mesh (actor_types *act, const char *fn, const char *kind);
86 int cal_load_mesh(actor_types *act, const char *fn, const char *kind);
87 void unqueue_cmd(int i);
88 #ifdef NEW_SOUND
89 int parse_actor_sounds(actor_types *act, const xmlNode *cfg);
90 #endif	//NEW_SOUND
91 
92 hash_table *emote_cmds = NULL;
93 hash_table *emotes = NULL;
94 int parse_actor_frames(actor_types *act, const xmlNode *cfg, const xmlNode *defaults);
95 
96 
97 #ifdef MORE_ATTACHED_ACTORS_DEBUG
98 static int thecount=0;
99 #endif
100 
101 
unfreeze_horse(int i)102 void unfreeze_horse(int i){
103 
104 			if(HAS_HORSE(i)&&MY_HORSE(i)->que[0]==wait_cmd) {
105 				//printf("%i, horse out of wait\n",thecount);
106 				unqueue_cmd(MY_HORSE_ID(i));
107 				MY_HORSE(i)->busy=0;
108 				set_on_idle(MY_HORSE_ID(i));
109 			}
110 }
111 
112 
cal_actor_set_random_idle(int id)113 void cal_actor_set_random_idle(int id)
114 {
115 	struct CalMixer *mixer;
116 	int i;
117 	int random_anim;
118 	int random_anim_index;
119 
120 	if (actors_list[id]->calmodel==NULL) return;
121 	//LOG_TO_CONSOLE(c_green2,"Randomizing");
122 	//if (actors_list[id]->cur_anim.anim_index==anim.anim_index) return;
123 	srand( (unsigned)time( NULL ) );
124 	mixer=CalModel_GetMixer(actors_list[id]->calmodel);
125 	//Stop previous animation if needed
126 	if (actors_list[id]->IsOnIdle!=1){
127 		if ((actors_list[id]->cur_anim.anim_index!=-1)&&(actors_list[id]->cur_anim.kind==0)) {
128 			CalMixer_ClearCycle(mixer,actors_list[id]->cur_anim.anim_index,0.05);
129 		}
130 		if ((actors_list[id]->cur_anim.anim_index!=-1)&&(actors_list[id]->cur_anim.kind==1)) {
131 			CalMixer_RemoveAction(mixer,actors_list[id]->cur_anim.anim_index);
132 		}
133 	}
134 
135 	for (i=0;i<actors_defs[actors_list[id]->actor_type].group_count;++i) {
136 		random_anim=rand()%(actors_defs[actors_list[id]->actor_type].idle_group[i].count+1);
137 		if (random_anim<actors_defs[actors_list[id]->actor_type].idle_group[i].count) random_anim_index=actors_defs[actors_list[id]->actor_type].idle_group[i].anim[random_anim].anim_index;
138 		else random_anim_index=-1;
139 		if (actors_list[id]->IsOnIdle==1) {
140 			if (actors_list[id]->cur_idle_anims[i].anim_index!=random_anim_index)
141 			CalMixer_ClearCycle(mixer,actors_list[id]->cur_idle_anims[i].anim_index,2.0);
142 		}
143 		if (actors_list[id]->cur_idle_anims[i].anim_index!=random_anim_index)
144 			if (random_anim_index>=0) CalMixer_BlendCycle(mixer,random_anim_index,0.5,0.05);
145 		//safe_snprintf(str, sizeof(str),"%d",random_anim);
146 		//LOG_TO_CONSOLE(c_green2,str);
147 		actors_list[id]->cur_idle_anims[i].anim_index=random_anim_index;
148 		//anim.anim_index,1.0,0.05);else
149 	}
150 
151 	//if (anim.kind==0) CalMixer_BlendCycle(mixer,anim.anim_index,1.0,0.05);else
152 	//CalMixer_ExecuteAction(mixer,anim.anim_index,0.0,0.0);
153 	//actors_list[id]->cur_anim=anim;
154 	//actors_list[id]->anim_time=0.0;
155 	CalModel_Update(actors_list[id]->calmodel,0.0001);//Make changes take effect now
156 	build_actor_bounding_box(actors_list[id]);
157 	if (use_animation_program)
158 	{
159 		set_transformation_buffers(actors_list[id]);
160 	}
161 	actors_list[id]->IsOnIdle= 1;
162 	actors_list[id]->cur_anim.duration= 0;
163 	actors_list[id]->anim_time= 0.0;
164 	actors_list[id]->last_anim_update= cur_time;
165 	actors_list[id]->cur_anim.anim_index= -1;
166 #ifdef NEW_SOUND
167 	if (check_sound_loops(actors_list[id]->cur_anim_sound_cookie))
168 		stop_sound(actors_list[id]->cur_anim_sound_cookie);
169 #endif // NEW_SOUND
170 	actors_list[id]->cur_anim_sound_cookie= 0;
171 	//if (actors_list[id]->cur_anim.anim_index==-1) actors_list[id]->busy=0;
172 }
173 
174 
unwindAngle_Degrees(float fAngle)175 float unwindAngle_Degrees( float fAngle )
176 {
177 	fAngle -= 360.0f * (int)( fAngle / 360.0f );
178 	if( fAngle < 0.0f )
179 		{
180 			fAngle += 360.0f;
181 		}
182 	return fAngle;
183 }
184 
185 
get_rotation_vector(float fStartAngle,float fEndAngle)186 float get_rotation_vector( float fStartAngle, float fEndAngle )
187 {
188 	float ccw = unwindAngle_Degrees( fStartAngle - fEndAngle );
189 	float cw = unwindAngle_Degrees( fEndAngle - fStartAngle );
190 	if(cw<ccw)return cw;
191 	else return -ccw;
192 }
193 
get_motion_vector(int move_cmd,int * dx,int * dy)194 int get_motion_vector(int move_cmd, int *dx, int *dy)
195 {
196 	int result = 1;
197     switch(move_cmd) {
198     case move_n:
199     case run_n:
200         *dx = 0;
201         *dy = 1;
202         break;
203     case move_s:
204     case run_s:
205         *dx = 0;
206         *dy = -1;
207         break;
208     case move_e:
209     case run_e:
210         *dx = 1;
211         *dy = 0;
212         break;
213     case move_w:
214     case run_w:
215         *dx = -1;
216         *dy = 0;
217         break;
218     case move_ne:
219     case run_ne:
220         *dx = 1;
221         *dy = 1;
222         break;
223     case move_se:
224     case run_se:
225         *dx = 1;
226         *dy = -1;
227         break;
228     case move_sw:
229     case run_sw:
230         *dx = -1;
231         *dy = -1;
232         break;
233     case move_nw:
234     case run_nw:
235         *dx = -1;
236         *dy = 1;
237         break;
238 
239     default:
240         *dx = 0;
241         *dy = 0;
242 		result = 0;
243         break;
244     }
245 	return result;
246 }
247 
248 #ifdef	ANIMATION_SCALING
update_actor_animation_speed(actor * a,const float time_diff)249 static Uint32 update_actor_animation_speed(actor* a, const float time_diff)
250 {
251 	float scale, seconds;
252 	Uint32 i, animations;
253 
254 	if (a == 0)
255 	{
256 		return 0;
257 	}
258 
259 	animations = 0;
260 
261 	for (i = 0; i < MAX_CMD_QUEUE; i++)
262 	{
263 		if ((a->que[i] != nothing) && (a->que[i] != wait_cmd))
264 		{
265 			animations++;
266 		}
267 	}
268 
269 	scale = a->animation_scale;
270 
271 	seconds = time_diff / 2000.0f;
272 
273 	if (animations > 2)
274 	{
275 		animations -= 2;
276 	}
277 	else
278 	{
279 		animations = 1;
280 	}
281 
282 	if (scale > animations)
283 	{
284 		scale = max2f(scale - seconds, animations);
285 	}
286 	else
287 	{
288 		if (scale < animations)
289 		{
290 			scale = min2f(scale + seconds, animations);
291 		}
292 	}
293 
294 	a->animation_scale = scale;
295 
296 	return scale * time_diff;
297 }
298 #endif	/* ANIMATION_SCALING */
299 
animate_actors()300 void animate_actors()
301 {
302 #ifdef	ANIMATION_SCALING
303 	static int last_update = 0;
304 	int i, actors_time_diff, time_diff, tmp_time_diff;
305 
306 	actors_time_diff = cur_time - last_update;
307 #else	/* ANIMATION_SCALING */
308 	int i;
309 	static int last_update= 0;
310     int time_diff = cur_time-last_update;
311     int tmp_time_diff;
312 #endif	/* ANIMATION_SCALING */
313 
314 	// lock the actors_list so that nothing can interere with this look
315 	LOCK_ACTORS_LISTS();	//lock it to avoid timing issues
316 	for(i=0; i<max_actors; i++) {
317 		if(actors_list[i]) {
318 #ifdef	ANIMATION_SCALING
319 			time_diff = update_actor_animation_speed(actors_list[i], actors_time_diff);
320 #endif	/* ANIMATION_SCALING */
321 			if(actors_list[i]->moving) {
322 #ifdef	ANIMATION_SCALING
323 				tmp_time_diff = min2i(actors_list[i]->movement_time_left + 40, time_diff);
324 
325 				actors_list[i]->x_pos += actors_list[i]->move_x_speed * tmp_time_diff;
326 				actors_list[i]->y_pos += actors_list[i]->move_y_speed * tmp_time_diff;
327 				actors_list[i]->z_pos += actors_list[i]->move_z_speed * tmp_time_diff;
328 #else	/* ANIMATION_SCALING */
329 				if (time_diff <= actors_list[i]->movement_time_left+40) {
330 					actors_list[i]->x_pos += actors_list[i]->move_x_speed*time_diff;
331 					actors_list[i]->y_pos += actors_list[i]->move_y_speed*time_diff;
332 					actors_list[i]->z_pos += actors_list[i]->move_z_speed*time_diff;
333 				}
334 				else {
335 					actors_list[i]->x_pos += actors_list[i]->move_x_speed*actors_list[i]->movement_time_left;
336 					actors_list[i]->y_pos += actors_list[i]->move_y_speed*actors_list[i]->movement_time_left;
337 					actors_list[i]->z_pos += actors_list[i]->move_z_speed*actors_list[i]->movement_time_left;
338 				}
339 #endif	/* ANIMATION_SCALING */
340 				actors_list[i]->movement_time_left -= time_diff;
341 				if(actors_list[i]->movement_time_left <= 0){	//we moved all the way
342 					Uint8 last_command;
343 					int dx, dy;
344 
345 					actors_list[i]->moving= 0;	//don't move next time, ok?
346 					//now, we need to update the x/y_tile_pos, and round off
347 					//the x/y_pos according to x/y_tile_pos
348 					last_command= actors_list[i]->last_command;
349 					//if(HAS_HORSE(i)) {MY_HORSE(i)->busy=0; if(actors_list[i]->actor_id==yourself) printf("%i, %s wakes up Horse\n",thecount, ACTOR(i)->actor_name);}
350 					if (get_motion_vector(last_command, &dx, &dy)) {
351 						actors_list[i]->x_tile_pos += dx;
352 						actors_list[i]->y_tile_pos += dy;
353 
354 						actors_list[i]->busy = 0;
355 						//if(actors_list[i]->actor_id==yourself) printf("%i, unbusy(moved)\n", thecount);
356 						//if(actors_list[i]->actor_id<0) printf("%i, unbusy horse(moved)\n", thecount);
357 
358 						if (actors_list[i]->que[0] >= move_n &&
359 							actors_list[i]->que[0] <= move_nw) {
360 							next_command();
361 						}
362 						else {
363 							actors_list[i]->x_pos= actors_list[i]->x_tile_pos*0.5;
364 							actors_list[i]->y_pos= actors_list[i]->y_tile_pos*0.5;
365 							actors_list[i]->z_pos= get_actor_z(actors_list[i]);
366 						}
367 					} else {
368 						actors_list[i]->busy = 0;
369 						//if(actors_list[i]->actor_id==yourself) printf("%i, unbusy(moved2)\n", thecount);
370 						//if(actors_list[i]->actor_id<0) printf("%i, unbusy horse(moved2)\n", thecount);
371 
372 					}
373 				}
374 			} //moving
375 
376 			if(actors_list[i]->rotating) {
377 #ifdef	ANIMATION_SCALING
378 				tmp_time_diff = min2i(actors_list[i]->rotate_time_left, time_diff);
379 				actors_list[i]->rotate_time_left -= time_diff;
380 
381 				//we rotated all the way
382 				if (actors_list[i]->rotate_time_left <= 0)
383 				{
384 					actors_list[i]->rotating = 0;//don't rotate next time, ok?
385 				}
386 #else	/* ANIMATION_SCALING */
387 				actors_list[i]->rotate_time_left -= time_diff;
388 				if (actors_list[i]->rotate_time_left <= 0) { //we rotated all the way
389 					actors_list[i]->rotating= 0;//don't rotate next time, ok?
390 					tmp_time_diff = time_diff + actors_list[i]->rotate_time_left;
391 /*
392 #ifdef MORE_ATTACHED_ACTORS
393 					if(actors_list[i]->actor_id==yourself) printf("%i, rot: %i\n",thecount,actors_list[i]->rotating);
394 					if(actors_list[i]->actor_id<0) printf("%i, (horse) rot: %i\n",thecount,actors_list[i]->rotating);
395 #endif
396 */
397 				}
398 				else {
399 					tmp_time_diff = time_diff;
400 				}
401 #endif	/* ANIMATION_SCALING */
402 				actors_list[i]->x_rot+= actors_list[i]->rotate_x_speed*tmp_time_diff;
403 				actors_list[i]->y_rot+= actors_list[i]->rotate_y_speed*tmp_time_diff;
404 				actors_list[i]->z_rot+= actors_list[i]->rotate_z_speed*tmp_time_diff;
405 				if(actors_list[i]->z_rot >= 360) {
406 					actors_list[i]->z_rot -= 360;
407 				} else if (actors_list[i]->z_rot <= 0) {
408 					actors_list[i]->z_rot += 360;
409 				}
410 				//if(actors_list[i]->actor_id==yourself) printf("%i, rotating: z_rot %f,  status %i-%i\n",thecount,actors_list[i]->z_rot,actors_list[i]->rotating,actors_list[i]->moving);
411 				//if(actors_list[i]->actor_id<0) printf("%i, rotating (horse): z_rot %f,  status %i-%i\n",thecount,actors_list[i]->z_rot,actors_list[i]->rotating,actors_list[i]->moving);
412 			}//rotating
413 
414 #ifdef	ANIMATION_SCALING
415 			actors_list[i]->anim_time += (time_diff*actors_list[i]->cur_anim.duration_scale)/1000.0;
416 #else	/* ANIMATION_SCALING */
417 			actors_list[i]->anim_time += ((cur_time-last_update)*actors_list[i]->cur_anim.duration_scale)/1000.0;
418 #endif	/* ANIMATION_SCALING */
419 			/*if(ACTOR(i)->anim_time>=ACTOR(i)->cur_anim.duration) {
420 				if (HAS_HORSE(i)||IS_HORSE(i)) {
421 						if(MY_HORSE(i)->anim_time<MY_HORSE(i)->cur_anim.duration) {
422 							MY_HORSE(i)->anim_time=MY_HORSE(i)->cur_anim.duration;
423 							printf("%i, ANIMATION FORCED\n",thecount);
424 						}
425 				}
426 			}*/
427 #ifndef	DYNAMIC_ANIMATIONS
428 			if (actors_list[i]->calmodel!=NULL){
429 				//check if emote animation is ended, then remove it
430 				handle_cur_emote(actors_list[i]);
431 
432 #ifdef MORE_EMOTES
433 				if(ACTOR(i)->startIdle!=ACTOR(i)->endIdle){
434 					if(do_transition(ACTOR(i))) {
435 						ACTOR(i)->stand_idle=ACTOR(i)->sit_idle=0; //force set_on_idle
436 						set_on_idle(i);
437 					}
438 				}
439 #endif
440 #ifdef	ANIMATION_SCALING
441 				CalModel_Update(actors_list[i]->calmodel, (time_diff * actors_list[i]->cur_anim.duration_scale) / 1000.0f);
442 #else	/* ANIMATION_SCALING */
443 				CalModel_Update(actors_list[i]->calmodel, (((cur_time-last_update)*actors_list[i]->cur_anim.duration_scale)/1000.0));
444 #endif	/* ANIMATION_SCALING */
445 				build_actor_bounding_box(actors_list[i]);
446 				{
447 				int wasbusy = ACTOR(i)->busy;
448 				missiles_rotate_actor_bones(actors_list[i]);
449 				if (ACTOR(i)->busy!=wasbusy&&HAS_HORSE(i)) {
450 					//if(actors_list[i]->actor_id==yourself) printf("%i, %s is no more busy due to missiles_rotate_actor_bones!! Setting the horse free...\n",thecount, ACTOR(i)->actor_name);
451 					unfreeze_horse(i);
452 				}
453 
454 				}
455 				if (use_animation_program)
456 				{
457 					set_transformation_buffers(actors_list[i]);
458 				}
459 			}
460 #endif	//DYNAMIC_ANIMATIONS
461 		}
462 	}
463 	// unlock the actors_list since we are done now
464 	UNLOCK_ACTORS_LISTS();
465 
466 	last_update = cur_time;
467 }
468 
unqueue_cmd(int i)469 void unqueue_cmd(int i){
470 	int k;
471 	int max_queue=0;
472 	//move que down with one command
473 	for(k=0;k<MAX_CMD_QUEUE-1;k++) {
474 		if(k>max_queue && actors_list[i]->que[k]!=nothing)max_queue=k;
475 			actors_list[i]->que[k]=actors_list[i]->que[k+1];
476 		}
477 	actors_list[i]->que[k]=nothing;
478 }
479 
480 
print_queue(actor * act)481 void print_queue(actor *act) {
482 	int k;
483 
484 	printf("   Actor %s queue:",act->actor_name);
485 	printf(" -->");
486 	for(k=0; k<MAX_CMD_QUEUE; k++){
487 			if(act->que[k]==enter_combat) printf("IC");
488 			if(act->que[k]==leave_combat) printf("LC");
489 			if(act->que[k]>=move_n&&act->que[k]<=move_nw) printf("M");
490 			if(act->que[k]>=turn_n&&act->que[k]<=turn_nw) printf("R");
491 			printf("%2i|",act->que[k]);
492 	}
493 	printf("\n");
494 	/*for(k=0; k<MAX_RANGE_ACTION_QUEUE; k++){
495 			printf("%2i-%2i|",act->range_actions[k].shot_type,act->range_actions[k].state);
496 	}
497 	printf("\n");
498 	*/
499 
500 	if (act->attached_actor >= 0) {
501 		printf("   Horse %s queue:",act->actor_name);
502 		printf(" -->");
503 		for(k=0; k<MAX_CMD_QUEUE; k++){
504 			if(actors_list[act->attached_actor]->que[k]==enter_combat) printf("IC");
505 			if(actors_list[act->attached_actor]->que[k]==leave_combat) printf("LC");
506 			if(actors_list[act->attached_actor]->que[k]>=move_n&&actors_list[act->attached_actor]->que[k]<=move_nw) printf("M");
507 			if(actors_list[act->attached_actor]->que[k]>=turn_n&&actors_list[act->attached_actor]->que[k]<=turn_nw) printf("R");
508 			printf("%2i|",actors_list[act->attached_actor]->que[k]);
509 		}
510 		printf("\n");
511 	}
512 
513 }
514 
attached_info(int i,int c)515 void attached_info(int i, int c){
516 					if(actors_list[i]->actor_id==yourself&&actors_list[i]->que[0]!=nothing) {
517 						printf("%i---------> DOING: %i -----------\n",c,actors_list[i]->que[0]);
518 						print_queue(actors_list[i]);
519 					}
520 					if(actors_list[i]->actor_id<0&&MY_HORSE(i)->actor_id==yourself&&actors_list[i]->que[0]!=wait_cmd&&actors_list[i]->que[0]!=nothing){
521 						printf("%i---------> DOING (horse): %i ---\n",c,actors_list[i]->que[0]);
522 						print_queue(actors_list[actors_list[i]->attached_actor]);
523 					}
524 
525 }
526 
flush_delayed_item_changes(actor * a)527 void flush_delayed_item_changes(actor *a)
528 {
529 	int item;
530 	for (item = 0; item < a->delayed_item_changes_count; ++item) {
531 		if (a->delayed_item_changes[item] < 0) {
532 			missiles_log_message("%s (%d): unwearing item type %d now\n",
533 								 a->actor_name,
534 								 a->actor_id,
535 								 a->delayed_item_type_changes[item]);
536 			unwear_item_from_actor(a->actor_id,
537 								   a->delayed_item_type_changes[item]);
538 		}
539 		else {
540 			missiles_log_message("%s (%d): wearing item type %d now\n",
541 								 a->actor_name,
542 								 a->actor_id,
543 								 a->delayed_item_type_changes[item]);
544 			actor_wear_item(a->actor_id,
545 							a->delayed_item_type_changes[item],
546 							a->delayed_item_changes[item]);
547 		}
548 	}
549 	a->delayed_item_changes_count = 0;
550 }
551 
552 int coun= 0;
move_to_next_frame()553 void move_to_next_frame()
554 {
555 	int i;
556 	//int numFrames=0;
557 	//char frame_exists;
558 	//struct CalMixer *mixer;
559 	//char str[255];
560 
561 	LOCK_ACTORS_LISTS();
562 	for(i=0;i<max_actors;i++) {
563 		if(actors_list[i]!=NULL) {
564 			if (actors_list[i]->calmodel!=NULL) {
565 			if ((ACTOR(i)->stop_animation==1)&&(ACTOR(i)->anim_time>=ACTOR(i)->cur_anim.duration)){
566 
567 
568 
569 					//if(actors_list[i]->actor_id==yourself) printf("%i, unbusy: anim %i, anim_time %f, duration %f\n",thecount,actors_list[i]->cur_anim.anim_index,actors_list[i]->anim_time,actors_list[i]->cur_anim.duration);
570 					//if(actors_list[i]->actor_id<0&&MY_HORSE(i)->actor_id==yourself) printf("%i, (horse) unbusy: anim %i, anim_time %f, duration %f\n",thecount,actors_list[i]->cur_anim.anim_index,actors_list[i]->anim_time,actors_list[i]->cur_anim.duration);
571 
572 					if(HAS_HORSE(i)) {
573 				//rotations during idle animation like when server sends turn_n..turn_nw
574 				//need to be synchronized on the minimum remaining animation time between
575 				//the idle of the horse and the actor.
576 						if(
577 						  /*(MY_HORSE(i)->anim_time<MY_HORSE(i)->cur_anim.duration)&&*/
578 						  MY_HORSE(i)->cur_anim.kind==cycle){
579 								//MY_HORSE(i)->anim_time=MY_HORSE(i)->cur_anim.duration;
580 								MY_HORSE(i)->busy=0;
581 								MY_HORSE(i)->in_aim_mode=0;
582 								set_on_idle(MY_HORSE_ID(i));
583 								//MY_HORSE(i)->stop_animation=0;
584 								//if(actors_list[i]->actor_id==yourself) printf("%i, %s stops Horse\n",thecount, ACTOR(i)->actor_name);
585 							}
586 					} else if (IS_HORSE(i)) {
587 						if(MY_HORSE(i)->anim_time<MY_HORSE(i)->cur_anim.duration) {
588 							//wait for actor
589 							//if(MY_HORSE(i)->actor_id==yourself) printf("%i, Horse waits for %s\n",thecount, MY_HORSE(i)->actor_name);
590 							continue;
591 						}
592 					}
593 
594 
595 
596 					actors_list[i]->busy=0;
597 					if (actors_list[i]->in_aim_mode == 2) {
598 						// we really leave the aim mode only when the animation is finished
599 						actors_list[i]->in_aim_mode = 0;
600 						missiles_log_message("%s (%d): leaving range mode finished!\n",
601 											 actors_list[i]->actor_name, actors_list[i]->actor_id);
602 
603 					}
604 				}
605 			}
606 			if (actors_list[i]->in_aim_mode == 0)
607 			{
608 				if (actors_list[i]->is_enhanced_model != 0)
609 				{
610 					if (get_actor_texture_ready(actors_list[i]->texture_id))
611 					{
612 						use_ready_actor_texture(actors_list[i]->texture_id);
613 					}
614 				}
615 
616 				if (actors_list[i]->delayed_item_changes_count > 0)
617 				{
618 					// we really leave the aim mode only when the animation is finished
619 					actors_list[i]->delay_texture_item_changes = 0;
620 
621 					// then we do all the item changes that have been delayed
622 					flush_delayed_item_changes(actors_list[i]);
623 
624 					actors_list[i]->delay_texture_item_changes = 1;
625 				}
626 			}
627 
628 			// we change the idle animation only when the previous one is finished
629 			if (actors_list[i]->stand_idle && actors_list[i]->anim_time >= actors_list[i]->cur_anim.duration - 0.2)
630 			{
631 				if (!is_actor_held(actors_list[i]))
632 				{
633 					set_on_idle(i);
634 				}
635 			}
636 
637 			if (actors_list[i]->cur_anim.anim_index==-1) {
638 				actors_list[i]->busy=0;
639 				//if(actors_list[i]->actor_id==yourself) printf("%i, unbusy(-1)\n", thecount);
640 				//if(actors_list[i]->actor_id<0) printf("%i, unbusy horse(-1)\n", thecount);
641 			}
642 
643 			//first thing, decrease the damage time, so we will see the damage splash only for 2 seconds
644 			if(actors_list[i]->damage_ms) {
645 				actors_list[i]->damage_ms-=80;
646 				if(actors_list[i]->damage_ms<0)actors_list[i]->damage_ms=0;
647 			}
648 
649 			//9 frames, not moving, and another command is queued farther on (based on how long we've done this action)
650 			if(!actors_list[i]->moving && !actors_list[i]->rotating){
651 
652 				/*	actors_list[i]->stop_animation=1;	//force stopping, not looping
653 					actors_list[i]->busy=0;	//ok, take the next command
654 					LOG_TO_CONSOLE(c_green2,"FREE");
655 					//Idle here?
656 				*/
657 			}
658 
659 			if(actors_list[i]->stop_animation) {
660 
661 				//we are done with this guy
662 				//Should we go into idle here?
663 			}
664 			if(!ACTOR(i)->busy){
665 				if(ACTOR(i)->attached_actor>=0&&ACTOR(i)->actor_id>=0&&
666 				(
667 				(ACTOR(i)->last_command>=enter_aim_mode&&ACTOR(i)->last_command<=aim_mode_fire)||
668 				(ACTOR(i)->last_command>=enter_combat&&ACTOR(i)->last_command<=leave_combat)
669 				)
670 				) {
671 					unfreeze_horse(i);
672 				}
673 			}
674 			if(HAS_HORSE(i)&&ACTOR(i)->in_aim_mode==3) { //when no_action==1
675 				ACTOR(i)->in_aim_mode=0;
676 				unfreeze_horse(i);
677 				//printf("%i,Unfreeze after no_action==1\n",thecount);
678 			}
679 		}
680 	}
681 	UNLOCK_ACTORS_LISTS();
682 }
683 
684 
685 
get_pose(actor * a,int pose_id,int pose_type,int held)686 struct cal_anim *get_pose(actor *a, int pose_id, int pose_type, int held) {
687 	hash_entry *he,*eh;
688 	emote_data *pose;
689 
690 	eh=hash_get(emotes,(void *)(uintptr_t)pose_id);
691 	pose = eh->item;
692 
693 	he=hash_get(actors_defs[a->actor_type].emote_frames, (void *)(uintptr_t)(pose->anims[pose_type][0][held]->ids[0]));
694 	if (he) return (struct cal_anim*) he->item;
695 	else return NULL;
696 }
697 
get_pose_frame(int actor_type,actor * a,int pose_type,int held)698 struct cal_anim *get_pose_frame(int actor_type, actor *a, int pose_type, int held){
699 
700 	hash_entry *he;
701 	int a_type=emote_actor_type(actor_type);
702 
703 	//find the pose. Pose is the first anim of the first frame
704 	if (a->poses[pose_type]) {
705 		//printf("getting pose for %s\n",a->actor_name);
706 		he=hash_get(actors_defs[actor_type].emote_frames, (void *)(uintptr_t)(a->poses[pose_type]->anims[a_type][0][held]->ids[0]));
707 		if (he) return (struct cal_anim*) he->item;
708 	}
709 	//no pose or no emote..set defaults
710 	if (!a->poses[pose_type]) {
711 		//printf("no pose for %s\n",a->actor_name);
712 		switch(pose_type){
713 			case EMOTE_SITTING:
714 				return &actors_defs[a->actor_type].cal_frames[cal_actor_idle_sit_frame];
715 			case EMOTE_STANDING:
716 				if(held)
717 				{
718 					attachment_props *att_props = get_attachment_props_if_held(a);
719 					if (att_props)
720 						return &att_props->cal_frames[cal_attached_idle_frame];
721 				}
722 				else
723 				{
724 					// 75% chance to do idle1
725 					if (actors_defs[a->actor_type].cal_frames[cal_actor_idle2_frame].anim_index != -1
726 						&& RAND(0, 3) == 0)
727 					{
728 						return &actors_defs[a->actor_type].cal_frames[cal_actor_idle2_frame]; //idle2
729 					} else {
730 						return &actors_defs[a->actor_type].cal_frames[cal_actor_idle1_frame]; //idle1
731 					}
732 				}
733 				break;
734 			case EMOTE_RUNNING:
735 				if(held)
736 				{
737 					attachment_props *att_props = get_attachment_props_if_held(a);
738 					if (att_props)
739 						return &att_props->cal_frames[cal_attached_run_frame/*get_held_actor_motion_frame(a)*/];
740 				} else
741 					return &actors_defs[actor_type].cal_frames[cal_actor_run_frame/*get_actor_motion_frame(a)*/];
742 				break;
743 			case EMOTE_WALKING:
744 				if(held)
745 				{
746 					attachment_props *att_props = get_attachment_props_if_held(a);
747 					if (att_props)
748 						return &att_props->cal_frames[cal_attached_walk_frame/*get_held_actor_motion_frame(a)*/];
749 				} else
750 					return &actors_defs[actor_type].cal_frames[cal_actor_walk_frame/*get_actor_motion_frame(a)*/];
751 				break;
752 			default:
753 				return NULL;
754 			break;
755 		}
756 	}
757 	return NULL;
758 }
759 
set_on_idle(int actor_idx)760 void set_on_idle(int actor_idx)
761 {
762     actor *a = actors_list[actor_idx];
763     if(!a->dead) {
764         a->stop_animation=0;
765 	//we have an emote idle, ignore the rest
766 	if(a->cur_emote.idle.anim_index>=0)
767 		return;
768 
769         if(a->fighting){
770 			if(a->attached_actor>=0) {
771 				//both for horses and actors
772 				if(IS_HORSE(actor_idx))
773 					cal_actor_set_anim(actor_idx,actors_defs[a->actor_type].cal_frames[cal_actor_combat_idle_frame]);
774 				else if (ACTOR_WEAPON(actor_idx)->turn_horse&&ACTOR(actor_idx)->horse_rotated) cal_actor_set_anim(actor_idx,actors_defs[a->actor_type].cal_frames[cal_actor_combat_idle_held_frame]);
775 				else cal_actor_set_anim(actor_idx,actors_defs[a->actor_type].cal_frames[cal_actor_combat_idle_held_unarmed_frame]);
776 			} else
777             cal_actor_set_anim(actor_idx,actors_defs[a->actor_type].cal_frames[cal_actor_combat_idle_frame]);
778         }
779         else if (a->in_aim_mode == 1) {
780 			if(a->actor_id<0){
781 				//ranging horse
782 				if(a->cur_anim.anim_index!=actors_defs[a->actor_type].cal_frames[cal_actor_idle1_frame].anim_index&&
783 				   a->cur_anim.anim_index!=actors_defs[a->actor_type].cal_frames[cal_actor_idle2_frame].anim_index){
784 				   //printf("%i, horse on idle from %i\n",thecount, a->cur_anim.anim_index);
785 				   cal_actor_set_anim(actor_idx, *get_pose_frame(a->actor_type,a,EMOTE_STANDING,0));
786 			}
787 			} else if(a->attached_actor>=0) {
788 				cal_actor_set_anim(actor_idx,actors_defs[a->actor_type].weapon[a->cur_weapon].cal_frames[cal_weapon_range_idle_held_frame]);
789 			} else
790             cal_actor_set_anim(actor_idx,actors_defs[a->actor_type].weapon[a->cur_weapon].cal_frames[cal_weapon_range_idle_frame]);
791         }
792         else if(!a->sitting) {
793             // we are standing, see if we can activate a stand idle
794             if(!a->stand_idle||a->cur_anim.anim_index<0){
795                 if (actors_defs[a->actor_type].group_count == 0){
796                 //if(a->actor_id<0) printf("%i, horse on standing idle from %i\n",thecount, a->cur_anim.anim_index);
797 
798 			attachment_props *att_props = get_attachment_props_if_held(a);
799 			if (att_props) {
800 				struct cal_anim *ca=get_pose_frame(a->actor_type,a,EMOTE_STANDING,1);
801 				cal_actor_set_anim(actor_idx, *ca);
802 				}
803 			else {
804 				struct cal_anim *ca=get_pose_frame(a->actor_type,a,EMOTE_STANDING,0);
805 				cal_actor_set_anim(actor_idx, *ca);
806 			}
807 
808 			//printf("setting standing pose\n");
809                 }
810                 else
811                 {
812                     cal_actor_set_random_idle(actor_idx);
813                     a->IsOnIdle=1;
814                 }
815 
816                 a->stand_idle=1;
817             }
818         } else	{
819             // we are sitting, see if we can activate the sit idle
820             if(!a->sit_idle||a->cur_anim.anim_index<0) {
821 		cal_actor_set_anim(actor_idx, *get_pose_frame(a->actor_type,a,EMOTE_SITTING,0));
822 		//printf("setting sitting pose\n");
823                 a->sit_idle=1;
824             }
825         }
826     }
827 }
828 
829 
830 
831 
832 
833 
834 
835 
836 
unqueue_emote(actor * act)837 void unqueue_emote(actor *act){
838 
839 	int k,max_queue = 0;
840 	// Move queue down one command
841 	for (k = 0; k < MAX_EMOTE_QUEUE - 1; k++) {
842 		if (k > max_queue && act->emote_que[k].origin != NO_EMOTE)
843 			max_queue = k;
844 		act->emote_que[k] = act->emote_que[k+1];
845 	}
846 	act->emote_que[k].origin = NO_EMOTE;
847 }
848 
handle_emote_command(int act_id,emote_command * command)849 int handle_emote_command(int act_id, emote_command *command)
850 {
851 	actor *act=actors_list[act_id];
852 	struct cal_anim *pose[4];
853 
854 	//check if emote is null. If so, reset emote anims
855 	if(!command->emote){
856 		//printf("reset emotes of actor %i\n",act->actor_id);
857 		cal_reset_emote_anims(act,1);
858 		unqueue_emote(act);
859 		return 1;
860 	}
861 
862 	//check if emote is timed out
863 	//printf("Handle emote %i created at %i for actor %i\n",command->emote->id,command->create_time,act->actor_id);
864 	if(command->create_time+command->emote->timeout<cur_time){
865 		//timed out
866 		//printf("Emote %i timed out\n",command->emote->id);
867 		unqueue_emote(act);
868 		return 1;
869 	} else if(!act->cur_emote.active){
870 		//there is still time to do it, and no emote going on:
871 		//check current frame, actor_type and emote flags
872 		int idle=0,actor_type,held;
873 		//struct cal_anim *defs;
874 		emote_frame *frames;
875 
876 		//barehanded?
877 		if((command->emote->barehanded&EMOTE_BARE_R)&&!is_actor_barehanded(act,EMOTE_BARE_R)){
878 			//printf("Remove weapon to play, waiting...\n");
879 			return 0;
880 		}
881 		if((command->emote->barehanded&EMOTE_BARE_L)&&!is_actor_barehanded(act,EMOTE_BARE_L)){
882 			//printf("Remove shield to play, waiting...\n");
883 			return 0;
884 		}
885 
886 
887 		held = (is_actor_held(act))?1:0;
888 		//printf("actor %i is held: %i\n",act_id,held);
889 		pose[EMOTE_STANDING] = get_pose_frame(act->actor_type,act,EMOTE_STANDING,held);
890 		pose[EMOTE_WALKING] = get_pose_frame(act->actor_type,act,EMOTE_WALKING,held);
891 		pose[EMOTE_SITTING] = get_pose_frame(act->actor_type,act,EMOTE_SITTING,held);
892 		pose[EMOTE_RUNNING] = get_pose_frame(act->actor_type,act,EMOTE_RUNNING,held);
893 
894 #ifdef MORE_EMOTES
895 
896 		if(command->emote->pose<=EMOTE_STANDING) {
897 			//we have a pose
898 			hash_entry *he;
899 			he=hash_get(actors_defs[actor_type].emote_frames, (void *)(uintptr_t)(command->emote->anims[act->actor_type][0][held]->ids[0]));
900 
901 			start_transition(act,((struct cal_anim*) he->item)->anim_index,300);
902 			act->poses[command->emote->pose]=command->emote;
903 			unqueue_emote(act);
904 			return 0;
905 		}
906 #endif
907 		/*printf("STANDING --> a: %i, c: %i\n",pose[EMOTE_STANDING]->anim_index, act->cur_anim.anim_index);
908 		printf("WALKING --> a: %i, c: %i\n",pose[EMOTE_WALKING]->anim_index, act->cur_anim.anim_index);
909 		printf("SITTING --> a: %i, c: %i\n",pose[EMOTE_SITTING]->anim_index, act->cur_anim.anim_index);
910 		printf("RUNNING --> a: %i, c: %i\n",pose[EMOTE_RUNNING]->anim_index, act->cur_anim.anim_index);
911 		*/
912 		if(pose[EMOTE_STANDING]&&pose[EMOTE_STANDING]->anim_index==act->cur_anim.anim_index) idle=EMOTE_STANDING;
913 		else
914 		if(pose[EMOTE_WALKING]&&pose[EMOTE_WALKING]->anim_index==act->cur_anim.anim_index) idle=EMOTE_WALKING;
915 		else
916 		if(pose[EMOTE_RUNNING]&&pose[EMOTE_RUNNING]->anim_index==act->cur_anim.anim_index) idle=EMOTE_RUNNING;
917 		else
918 		if(pose[EMOTE_SITTING]&&pose[EMOTE_SITTING]->anim_index==act->cur_anim.anim_index) idle=EMOTE_SITTING;
919 		else if(act->cur_anim.anim_index<0) {
920 			//we have an emote idle. Remove it and try again
921 			cal_reset_emote_anims(act,1);
922 			set_on_idle(act_id);
923 			return 0;
924 		} else {
925 			//printf("No suitable state for !held\n");
926 			unqueue_emote(act);
927 			return 1;
928 		}
929 		actor_type=emote_actor_type(act->actor_type);
930 		frames=command->emote->anims[actor_type][idle][held];
931 
932 		//we have a emote and not already playing one
933 		//printf("we have anim...actor: %i, held: %i, frames: %p, idle: %i\n",act->actor_id, held,frames,idle);
934 		if (!frames) {
935 			//not ready yet, try later
936 			//printf("but not ready yet\n");
937 			return 0;
938 		} else {
939 			//ready! set emote and unqueue
940 			//printf("ready!!\n");
941 			cal_actor_set_emote_anim(act, frames);
942 			if(HAS_HORSE(act_id)) {
943 				MY_HORSE(act_id)->cur_emote.active=1; //synch with horse!!
944 				//cal_actor_set_emote_anim(MY_HORSE(act_id), frames);
945 			}
946 			//printf("unqueue\n");
947 			unqueue_emote(act);
948 			//LOG_TO_CONSOLE(c_green2, "Emote command");
949 			return 0;
950 		}
951 
952 	}
953 	return 0;
954 }
955 
rotate_actor_and_horse_by(int id,int mul,float angle)956 void rotate_actor_and_horse_by(int id, int mul, float angle){
957 
958 			//printf("%i. ACTOR %s (rotating: %i): time left -> %i, z speed -> %f\n",thecount,ACTOR(id)->actor_name,actors_list[id]->rotating,actors_list[id]->rotate_time_left,actors_list[id]->rotate_z_speed);
959 
960 			if(!ACTOR(id)->rotating){
961 				ACTOR(id)->rotate_z_speed=(float)mul*angle/(float)HORSE_FIGHT_TIME;
962 				ACTOR(id)->rotate_time_left=HORSE_FIGHT_TIME;
963 				ACTOR(id)->rotating=1;
964 				ACTOR(id)->stop_animation=1;
965 				ACTOR(id)->horse_rotated=(mul<0) ? (1):(0); //<0 enter fight, >=0 leave fight
966 				MY_HORSE(id)->rotate_z_speed=(float)mul*angle/(float)HORSE_FIGHT_TIME;
967 				MY_HORSE(id)->rotate_time_left=HORSE_FIGHT_TIME;
968 				MY_HORSE(id)->rotating=1;
969 				MY_HORSE(id)->stop_animation=1;
970 			}
971 
972 }
973 
rotate_actor_and_horse(int id,int mul)974 void rotate_actor_and_horse(int id, int mul){
975 	rotate_actor_and_horse_by(id,mul,HORSE_FIGHT_ROTATION);
976 }
977 
rotate_actor_and_horse_range(int id,int mul)978 void rotate_actor_and_horse_range(int id, int mul){
979 	rotate_actor_and_horse_by(id,mul,HORSE_RANGE_ROTATION);
980 }
981 
982 
983 //in case the actor is not busy, and has commands in it's que, execute them
next_command()984 void next_command()
985 {
986 	int i, index;
987 	int max_queue=0;
988 
989 
990 #ifdef MORE_ATTACHED_ACTORS_DEBUG
991 	thecount++;
992 #endif
993 
994 	for(i=0;i<max_actors;i++){
995 		if(!actors_list[i])continue;//actor exists?
996 		if(actors_list[i]->que[0]>=emote_cmd
997 		&&actors_list[i]->que[0]<wait_cmd
998 		){
999 			int k;
1000 			add_emote_to_actor(actors_list[i]->actor_id,actors_list[i]->que[0]);
1001 			//actors_list[i]->stop_animation=1;
1002 			//move que down with one command
1003 			for(k=0;k<MAX_CMD_QUEUE-1;k++) {
1004 				if(k>max_queue && actors_list[i]->que[k]!=nothing)max_queue=k;
1005 				actors_list[i]->que[k]=actors_list[i]->que[k+1];
1006 			}
1007 			actors_list[i]->que[max_queue]=nothing;
1008 		}
1009 		if(!actors_list[i]->busy){//Are we busy?
1010 			//are we playing an emote?
1011 			if(actors_list[i]->cur_emote.active
1012 			&&!(actors_list[i]->que[0]>=move_n&&actors_list[i]->que[0]<=move_nw&&actors_list[i]->last_command>=move_n&&actors_list[i]->last_command<=move_nw)
1013 			&&!HAS_HORSE(i)
1014 			) { continue;}
1015 
1016 			// If the que is empty, check for an emote to display
1017 			while (actors_list[i]->emote_que[0].origin != NO_EMOTE)
1018 				if(!handle_emote_command(i, &actors_list[i]->emote_que[0])) break;
1019 			if(actors_list[i]->que[0]==nothing){//Is the queue empty?
1020 				//if que is empty, set on idle
1021 				set_on_idle(i);
1022 				//synch_attachment(i);
1023 				actors_list[i]->last_command=nothing;//prevents us from not updating the walk/run animation
1024 			} else {
1025 				int actor_type;
1026 				int last_command=actors_list[i]->last_command;
1027 				float z_rot=actors_list[i]->z_rot;
1028 				float targeted_z_rot;
1029 				int no_action = 0;
1030 
1031 				actors_list[i]->sit_idle=0;
1032 				actors_list[i]->stand_idle=0;
1033 
1034 #ifndef DISABLE_RANGE_MODE_EXIT_BUGFIX
1035 				if (actors_list[i]->is_enhanced_model && actors_list[i]->in_aim_mode == 1 &&
1036 					(actors_list[i]->que[0] < enter_aim_mode || actors_list[i]->que[0] > missile_critical) &&
1037 					(actors_list[i]->que[0] < turn_n || actors_list[i]->que[0] > turn_nw))
1038 				{
1039 					actor *a = actors_list[i];
1040 
1041 					LOG_ERROR("%s: %d: command incompatible with range mode detected: %d", __FUNCTION__, __LINE__, actors_list[i]->que[0]);
1042 					missiles_log_message("%s (%d): forcing aim mode exit", a->actor_name, a->actor_id);
1043 					a->cal_h_rot_start = 0.0;
1044 					a->cal_v_rot_start = 0.0;
1045 					a->cal_h_rot_end = 0.0;
1046 					a->cal_v_rot_end = 0.0;
1047 					a->cal_rotation_blend = 1.0;
1048 					a->cal_rotation_speed = 0.0;
1049 					a->cal_last_rotation_time = cur_time;
1050 					a->are_bones_rotating = 1;
1051 					a->in_aim_mode = 0;
1052 					flush_delayed_item_changes(a);
1053 				}
1054 #endif // DISABLE_RANGE_MODE_EXIT_BUGFIX
1055 
1056 				actor_type=actors_list[i]->actor_type;
1057 #ifdef MORE_ATTACHED_ACTORS_DEBUG
1058 				//just for debugging
1059 				attached_info(i,thecount);
1060 #endif
1061 				switch(actors_list[i]->que[0]) {
1062 					case kill_me:
1063 /*						if(actors_list[i]->remapped_colors)
1064 						glDeleteTextures(1,&actors_list[i]->texture_id);
1065 						ec_actor_delete(actors_list[i]);
1066 						free(actors_list[i]);
1067 						actors_list[i]=0;*/ //Obsolete
1068 						break;
1069 					case die1:
1070 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_die1_frame]);
1071 						actors_list[i]->stop_animation=1;
1072 						actors_list[i]->dead=1;
1073 						break;
1074 					case die2:
1075 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_die2_frame]);
1076 						actors_list[i]->stop_animation=1;
1077 						actors_list[i]->dead=1;
1078 						break;
1079 					case pain1:
1080 					case pain2: {
1081 						int painframe = (actors_list[i]->que[0]==pain1) ? (cal_actor_pain1_frame):(cal_actor_pain2_frame);
1082 						attachment_props *att_props = get_attachment_props_if_held(actors_list[i]);
1083 						if (att_props) {
1084 							if(HAS_HORSE(i)&&!ACTOR_WEAPON(i)->unarmed) {
1085 							cal_actor_set_anim(i, att_props->cal_frames[cal_attached_pain_armed_frame]);
1086 							} else
1087 							cal_actor_set_anim(i, att_props->cal_frames[cal_attached_pain_frame]);
1088 						} else
1089 
1090 							cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[painframe]);
1091 						actors_list[i]->stop_animation=1;
1092 						break;
1093 					}
1094 /*					case pain2: {
1095 						attachment_props *att_props = get_attachment_props_if_held(actors_list[i]);
1096 						if (att_props)
1097 							cal_actor_set_anim(i, att_props->cal_frames[cal_attached_pain_frame]);
1098 						else
1099 							cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_pain2_frame]);
1100 						actors_list[i]->stop_animation=1;
1101 						break;
1102 					}
1103 */					case pick:
1104 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_pick_frame]);
1105 						actors_list[i]->stop_animation=1;
1106 						break;
1107 					case drop:
1108 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_drop_frame]);
1109 						actors_list[i]->stop_animation=1;
1110 						break;
1111 					case harvest:
1112 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_harvest_frame]);
1113 						actors_list[i]->stop_animation=1;
1114 						LOG_TO_CONSOLE(c_green2,"Harvesting!");
1115 						break;
1116 					case cast:
1117 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_attack_cast_frame]);
1118 						actors_list[i]->stop_animation=1;
1119 						break;
1120 					case ranged:
1121 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_attack_ranged_frame]);
1122 						actors_list[i]->stop_animation=1;
1123 						break;
1124 					case sit_down:
1125 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_sit_down_frame]);
1126 						actors_list[i]->stop_animation=1;
1127 						actors_list[i]->sitting=1;
1128 						if(actors_list[i]->actor_id==yourself)
1129 							you_sit=1;
1130 						break;
1131 					case stand_up:
1132 						//LOG_TO_CONSOLE(c_green2,"stand_up");
1133 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_stand_up_frame]);
1134 						actors_list[i]->stop_animation=1;
1135 						actors_list[i]->sitting=0;
1136 						if(actors_list[i]->actor_id==yourself)
1137 							you_sit=0;
1138 						break;
1139 					case enter_combat:
1140 					case leave_combat:
1141 						{
1142 						int fight_k = (actors_list[i]->que[0]==enter_combat) ? (1):(0);
1143 						int combat_frame = (fight_k) ? (cal_actor_in_combat_frame):(cal_actor_out_combat_frame);
1144 						int combat_held_frame = (fight_k) ? (cal_actor_in_combat_held_frame):(cal_actor_out_combat_held_frame);
1145 						int combat_held_unarmed_frame = (fight_k) ? (cal_actor_in_combat_held_unarmed_frame):(cal_actor_out_combat_held_unarmed_frame);
1146 						int mul_angle = (fight_k) ? (-1):(1);
1147 
1148 						if(HAS_HORSE(i)){
1149 							//rotate horse and actor if needed
1150 							if(ACTOR_WEAPON(i)->turn_horse) {
1151 							if(fight_k||ACTOR(i)->horse_rotated) rotate_actor_and_horse(i,mul_angle);
1152 							cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[combat_held_frame]);
1153 							}
1154 							else cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[combat_held_unarmed_frame]);
1155 							//horse enter combat
1156 							MY_HORSE(i)->fighting=fight_k;
1157 							MY_HORSE(i)->stop_animation=1;
1158 							cal_actor_set_anim(MY_HORSE_ID(i),actors_defs[MY_HORSE(i)->actor_type].cal_frames[combat_frame]);
1159 						} else
1160 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[combat_frame]);
1161 
1162 						actors_list[i]->stop_animation=1;
1163 						actors_list[i]->fighting=fight_k;
1164 						}
1165 						break;
1166 /*					case leave_combat:
1167 #ifdef MORE_ATTACHED_ACTORS
1168 						if(HAS_HORSE(i)){
1169 							cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_out_combat_held_frame]);
1170 							//rotate counterclowwise horse and actor
1171 							add_rotation_to_actor(i,HORSE_FIGHT_ROTATION,HORSE_FIGHT_TIME);
1172 							rotate_actor(MY_HORSE_ID(i),HORSE_FIGHT_ROTATION,HORSE_FIGHT_TIME);
1173 
1174 							cal_actor_set_anim(MY_HORSE_ID(i),actors_defs[MY_HORSE(i)->actor_type].cal_frames[cal_actor_out_combat_frame]);
1175 							MY_HORSE(i)->stop_animation=1;
1176 							MY_HORSE(i)->fighting=0;
1177 						} else
1178 #endif
1179 						cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[cal_actor_out_combat_frame]);
1180 						actors_list[i]->stop_animation=1;
1181 						actors_list[i]->fighting=0;
1182 						break;
1183 */
1184 					case attack_up_1:
1185 					case attack_up_2:
1186 					case attack_up_3:
1187 					case attack_up_4:
1188 					case attack_up_5:
1189 					case attack_up_6:
1190 					case attack_up_7:
1191 					case attack_up_8:
1192 					case attack_up_9:
1193 					case attack_up_10:
1194 					case attack_down_1:
1195 					case attack_down_2:
1196 					case attack_down_3:
1197 					case attack_down_4:
1198 					case attack_down_5:
1199 					case attack_down_6:
1200 					case attack_down_7:
1201 					case attack_down_8:
1202 					case attack_down_9:
1203 					case attack_down_10:
1204 						index = -1;
1205 						switch (actors_list[i]->que[0])
1206 						{
1207 							case attack_down_10:
1208 								index++;
1209 							// fall-through - suppress the compile warning with this comment
1210 							case attack_down_9:
1211 								index++;
1212 							// fall-through
1213 							case attack_down_8:
1214 								index++;
1215 							// fall-through
1216 							case attack_down_7:
1217 								index++;
1218 							// fall-through
1219 							case attack_down_6:
1220 								index++;
1221 							// fall-through
1222 							case attack_down_5:
1223 								index++;
1224 							// fall-through
1225 							case attack_down_4:
1226 								index++;
1227 							// fall-through
1228 							case attack_down_3:
1229 								index++;
1230 							// fall-through
1231 							case attack_down_2:
1232 								index++;
1233 							// fall-through
1234 							case attack_down_1:
1235 								index++;
1236 							// fall-through
1237 							case attack_up_10:
1238 								index++;
1239 							// fall-through
1240 							case attack_up_9:
1241 								index++;
1242 							// fall-through
1243 							case attack_up_8:
1244 								index++;
1245 							// fall-through
1246 							case attack_up_7:
1247 								index++;
1248 							// fall-through
1249 							case attack_up_6:
1250 								index++;
1251 							// fall-through
1252 							case attack_up_5:
1253 								index++;
1254 							// fall-through
1255 							case attack_up_4:
1256 								index++;
1257 							// fall-through
1258 							case attack_up_3:
1259 								index++;
1260 							// fall-through
1261 							case attack_up_2:
1262 								index++;
1263 							// fall-through
1264 							case attack_up_1:
1265 								index++;
1266 								break;
1267 							default:
1268 								break;
1269 						}
1270 						if (actors_list[i]->is_enhanced_model) {
1271 							if(HAS_HORSE(i)/*actors_list[i]->attached_actor>=0&&actors_list[i]->actor_id>=0*/) {
1272 								//actor does combat anim
1273 								index+=cal_weapon_attack_up_1_held_frame; //30; //select held weapon animations
1274 								cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[index]);
1275 							} else {
1276 								//normal weapon animation
1277 								cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[index]);
1278 							}
1279 						} else {
1280 							//non enhanced models
1281 						if(HAS_HORSE(i)) {
1282 								//non enhanced model with a horse
1283 								index+=cal_actor_attack_up_1_held_frame;
1284 								cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[index]);
1285 						} else
1286 						 {
1287 							//select normal actor att frames
1288 							index +=cal_actor_attack_up_1_frame;
1289 							cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[index]);
1290 						 }
1291 						}
1292 						actors_list[i]->stop_animation=1;
1293 						actors_list[i]->fighting=1;
1294 
1295 #ifdef NEW_SOUND
1296 						// Maybe play a battlecry sound
1297 						add_battlecry_sound(actors_list[i]);
1298 #endif // NEW_SOUND
1299 						//check if a horse rotation is needed
1300 						if(HAS_HORSE(i)&&!ACTOR(i)->horse_rotated&&ACTOR_WEAPON(i)->turn_horse) {
1301 							//horse, not rotated, to be rotated -> do rotation
1302 							rotate_actor_and_horse(i,-1);
1303 						} else if (HAS_HORSE(i)&&ACTOR(i)->horse_rotated&&!ACTOR_WEAPON(i)->turn_horse) {
1304 							//horse, rotated, not to be rotated -> undo rotation
1305 							ACTOR(i)->horse_rotated=0;
1306 							rotate_actor_and_horse(i,1);
1307 
1308 						}
1309 						break;
1310 					case turn_left:
1311 					case turn_right:
1312 					{
1313 						int mul= (actors_list[i]->que[0]==turn_left) ? (1):(-1);
1314 						int turnframe=(actors_list[i]->que[0]==turn_left) ? (cal_actor_turn_left_frame):(cal_actor_turn_right_frame);
1315 
1316 						//LOG_TO_CONSOLE(c_green2,"turn left");
1317 						actors_list[i]->rotate_z_speed=mul*45.0/540.0;
1318 						actors_list[i]->rotate_time_left=540;
1319 						actors_list[i]->rotating=1;
1320 						//generate a fake movement, so we will know when to make the actor
1321 						//not busy
1322 						actors_list[i]->move_x_speed=0;
1323 						actors_list[i]->move_y_speed=0;
1324 						actors_list[i]->move_z_speed=0;
1325 						actors_list[i]->movement_time_left=540;
1326 						actors_list[i]->moving=1;
1327 						//test
1328 						if(!actors_list[i]->fighting){
1329 							attachment_props *att_props = get_attachment_props_if_held(actors_list[i]);
1330 							if (att_props)
1331 								cal_actor_set_anim(i, *get_pose_frame(actors_list[i]->actor_type,actors_list[i],EMOTE_MOTION(actors_list[i]),1));
1332 							else
1333 							cal_actor_set_anim(i,actors_defs[actor_type].cal_frames[turnframe]);
1334 						}
1335 						actors_list[i]->stop_animation=0;
1336 						break;
1337 					}
1338 				case enter_aim_mode:
1339 					missiles_log_message("%s (%d): cleaning the queue from enter_aim_mode command",
1340 										 actors_list[i]->actor_name, actors_list[i]->actor_id);
1341 					missiles_clean_range_actions_queue(actors_list[i]);
1342 
1343 					if (actors_list[i]->in_aim_mode == 0) {
1344 						missiles_log_message("%s (%d): enter in aim mode", actors_list[i]->actor_name, actors_list[i]->actor_id);
1345 						//if(actors_list[i]->actor_id==yourself) printf("%i, enter aim 0\n",thecount);
1346 						if(actors_list[i]->attached_actor>=0){
1347 							if (!ACTOR(i)->horse_rotated) {rotate_actor_and_horse_range(i,-1); ACTOR(i)->horse_rotated=1;}						//set the horse aim mode
1348 							actors_list[actors_list[i]->attached_actor]->in_aim_mode=1;
1349 							//stop_attachment(i); //add a wait
1350 							//we could start a horse_ranged_in
1351 							set_on_idle(actors_list[i]->attached_actor);
1352 							cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_in_held_frame]);
1353 						} else
1354 							cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_in_frame]);
1355 
1356 						actors_list[i]->cal_h_rot_start = 0.0;
1357 						actors_list[i]->cal_v_rot_start = 0.0;
1358 						if (actors_list[i]->range_actions_count != 1) {
1359 							LOG_ERROR("%s (%d): entering in range mode with an non empty range action queue!",
1360 									  actors_list[i]->actor_name, actors_list[i]->actor_id);
1361 						}
1362 					}
1363 					else {
1364                         float range_rotation;
1365 						range_action *action = &actors_list[i]->range_actions[0];
1366 						//if(actors_list[i]->actor_id==yourself) printf("%i, enter aim %i\n",thecount,actors_list[i]->in_aim_mode);
1367 						missiles_log_message("%s (%d): aiming again (time=%d)", actors_list[i]->actor_name, actors_list[i]->actor_id, cur_time);
1368 						if(HAS_HORSE(i)) {
1369 						cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_idle_held_frame]);
1370 						//if (!ACTOR(i)->horse_rotated) {rotate_actor_and_horse(i,-1); ACTOR(i)->horse_rotated=1;}
1371 
1372 						}
1373 						else
1374 						cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_idle_frame]);
1375 						actors_list[i]->cal_h_rot_start = (actors_list[i]->cal_h_rot_start *
1376 														   (1.0 - actors_list[i]->cal_rotation_blend) +
1377 														   actors_list[i]->cal_h_rot_end *
1378 														   actors_list[i]->cal_rotation_blend);
1379 						actors_list[i]->cal_v_rot_start = (actors_list[i]->cal_v_rot_start *
1380 														   (1.0 - actors_list[i]->cal_rotation_blend) +
1381 														   actors_list[i]->cal_v_rot_end *
1382 														   actors_list[i]->cal_rotation_blend);
1383 
1384 						/* we look if the actor is still around and if yes,
1385 						 * we recompute it's position */
1386 						if (action->aim_actor >= 0) {
1387 							actor *aim_actor = get_actor_ptr_from_id(action->aim_actor);
1388 							if (aim_actor) {
1389 								cal_get_actor_bone_absolute_position(aim_actor, get_actor_bone_id(aim_actor, body_top_bone), NULL, action->aim_position);
1390 							}
1391 						}
1392 
1393 
1394 						if(HAS_HORSE(i)) ACTOR(i)->z_rot+=HORSE_RANGE_ROTATION;
1395 						range_rotation = missiles_compute_actor_rotation(&actors_list[i]->cal_h_rot_end,
1396 																		 &actors_list[i]->cal_v_rot_end,
1397 																		 actors_list[i], action->aim_position);
1398 						if(HAS_HORSE(i)) ACTOR(i)->z_rot-=HORSE_RANGE_ROTATION;
1399 						actors_list[i]->cal_rotation_blend = 0.0;
1400 						actors_list[i]->cal_rotation_speed = 1.0/360.0;
1401                         actors_list[i]->cal_last_rotation_time = cur_time;
1402 						actors_list[i]->are_bones_rotating = 1;
1403 						actors_list[i]->stop_animation = 1;
1404 						if (action->state == 0) action->state = 1;
1405 
1406 						if (range_rotation != 0.0) {
1407 							missiles_log_message("%s (%d): not facing its target => client side rotation needed",
1408                                                  actors_list[i]->actor_name, actors_list[i]->actor_id);
1409 							if (actors_list[i]->rotating) {
1410 								range_rotation += actors_list[i]->rotate_z_speed * actors_list[i]->rotate_time_left;
1411 							}
1412 							actors_list[i]->rotate_z_speed = range_rotation/360.0;
1413 							actors_list[i]->rotate_time_left=360;
1414 							actors_list[i]->rotating=1;
1415 							if(HAS_HORSE(i)){
1416 								//printf("rotating the horse client side!\n");
1417 								actors_list[actors_list[i]->attached_actor]->rotate_z_speed=range_rotation/360.0;
1418 								actors_list[actors_list[i]->attached_actor]->rotate_time_left=360;
1419 								actors_list[actors_list[i]->attached_actor]->rotating=1;
1420 							}
1421 						}
1422 					}
1423 					break;
1424 
1425 				case leave_aim_mode:
1426 					if (actors_list[i]->in_aim_mode != 1) {
1427 						if (actors_list[i]->cal_rotation_blend < 0.0 ||
1428 							(actors_list[i]->cal_h_rot_end == 0.0 &&
1429 							 actors_list[i]->cal_v_rot_end == 0.0)) {
1430 							LOG_ERROR("next_command: trying to leave range mode while we are not in it => aborting safely...");
1431 							no_action = 1;
1432 							if (ACTOR(i)->horse_rotated) {rotate_actor_and_horse_range(i,1); ACTOR(i)->horse_rotated=0;}
1433 							break;
1434 						}
1435 						else {
1436 							LOG_ERROR("next_command: trying to leave range mode while we are not in it => continuing because of a wrong actor bones rotation!");
1437 						}
1438 					}
1439 
1440 					missiles_log_message("%s (%d): leaving aim mode", actors_list[i]->actor_name, actors_list[i]->actor_id);
1441 					if(HAS_HORSE(i)) {
1442 					cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_out_held_frame]);
1443 					if (ACTOR(i)->horse_rotated) {rotate_actor_and_horse_range(i,1); ACTOR(i)->horse_rotated=0;}
1444 					}
1445 					else
1446 					cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_out_frame]);
1447 					actors_list[i]->cal_h_rot_start = (actors_list[i]->cal_h_rot_start *
1448 													   (1.0 - actors_list[i]->cal_rotation_blend) +
1449 													   actors_list[i]->cal_h_rot_end *
1450 													   actors_list[i]->cal_rotation_blend);
1451 					actors_list[i]->cal_v_rot_start = (actors_list[i]->cal_v_rot_start *
1452 													   (1.0 - actors_list[i]->cal_rotation_blend) +
1453 													   actors_list[i]->cal_v_rot_end *
1454 													   actors_list[i]->cal_rotation_blend);
1455 					actors_list[i]->cal_h_rot_end = 0.0;
1456 					actors_list[i]->cal_v_rot_end = 0.0;
1457 					actors_list[i]->cal_rotation_blend = 0.0;
1458 					actors_list[i]->cal_rotation_speed = 1.0/360.0;
1459                     actors_list[i]->cal_last_rotation_time = cur_time;
1460 					actors_list[i]->are_bones_rotating = 1;
1461 					actors_list[i]->in_aim_mode = 2;
1462 					actors_list[i]->stop_animation = 1;
1463 					break;
1464 
1465 /* 				case aim_mode_reload: */
1466 /* 					missiles_log_message("%s (%d): reload after next fire", actors_list[i]->actor_name, actors_list[i]->actor_id); */
1467 /* 					actors_list[i]->reload = 1; */
1468 /*  					no_action = 1; */
1469 /* 					break; */
1470 
1471 				case aim_mode_fire:
1472 					{
1473 						range_action *action = &actors_list[i]->range_actions[0];
1474 						action->state = 3;
1475 
1476 						if (actors_list[i]->in_aim_mode != 1) {
1477 							LOG_ERROR("next_command: trying to fire an arrow out of range mode => aborting!");
1478 							no_action = 1;
1479 							missiles_log_message("%s (%d): cleaning the queue from aim_mode_fire command (error)",
1480 												 actors_list[i]->actor_name, actors_list[i]->actor_id);
1481 							missiles_clean_range_actions_queue(actors_list[i]);
1482 							break;
1483 						}
1484 
1485 						if (action->reload) {
1486 							missiles_log_message("%s (%d): fire and reload", actors_list[i]->actor_name, actors_list[i]->actor_id);
1487 							// launch fire and reload animation
1488 
1489 							//if(actors_list[i]->actor_id==yourself) printf("%i, enter reload\n",thecount);
1490 							if(HAS_HORSE(i))
1491 							cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_fire_held_frame]);
1492 							else
1493 							cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_fire_frame]);
1494 							actors_list[i]->in_aim_mode = 1;
1495 						}
1496 						else {
1497 							missiles_log_message("%s (%d): fire and leave aim mode", actors_list[i]->actor_name, actors_list[i]->actor_id);
1498 							// launch fire and leave aim mode animation
1499 
1500 							//if(actors_list[i]->actor_id==yourself) printf("%i, enter fire & leave\n",thecount);
1501 							if(HAS_HORSE(i))
1502 							cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_fire_out_held_frame]);
1503 							else
1504 							cal_actor_set_anim(i,actors_defs[actor_type].weapon[actors_list[i]->cur_weapon].cal_frames[cal_weapon_range_fire_out_frame]);
1505 							actors_list[i]->in_aim_mode = 2;
1506 						}
1507 
1508 						actors_list[i]->cal_h_rot_start = (actors_list[i]->cal_h_rot_start *
1509 														   (1.0 - actors_list[i]->cal_rotation_blend) +
1510 														   actors_list[i]->cal_h_rot_end *
1511 														   actors_list[i]->cal_rotation_blend);
1512 						actors_list[i]->cal_v_rot_start = (actors_list[i]->cal_v_rot_start *
1513 														   (1.0 - actors_list[i]->cal_rotation_blend) +
1514 														   actors_list[i]->cal_v_rot_end *
1515 														   actors_list[i]->cal_rotation_blend);
1516 						actors_list[i]->cal_h_rot_end = 0.0;
1517 						actors_list[i]->cal_v_rot_end = 0.0;
1518 						actors_list[i]->cal_rotation_blend = 0.0;
1519 						actors_list[i]->cal_rotation_speed = 1.0/360.0;
1520 						actors_list[i]->cal_last_rotation_time = cur_time;
1521 						actors_list[i]->are_bones_rotating = 1;
1522 						actors_list[i]->stop_animation = 1;
1523 
1524 						/* In case of a missed shot due to a collision with an actor,
1525 						 * the server send the position of the actor with 0.0 for the Z coordinate.
1526 						 * So we have to compute the coordinate of the ground at this position.
1527 						 */
1528 						if (action->shot_type == MISSED_SHOT &&
1529 							action->fire_position[2] == 0.0) {
1530 							int tile_x = (int)(action->fire_position[0]*2.0);
1531 							int tile_y = (int)(action->fire_position[1]*2.0);
1532 							action->fire_position[2] = get_tile_height(tile_x, tile_y);
1533 							missiles_log_message("missed shot detected: new height computed: %f", action->fire_position[2]);
1534 						}
1535 						else if (action->fire_actor >= 0) {
1536 							actor *fire_actor = get_actor_ptr_from_id(action->fire_actor);
1537 							if (fire_actor) {
1538 								cal_get_actor_bone_absolute_position(fire_actor, get_actor_bone_id(fire_actor, body_top_bone), NULL, action->fire_position);
1539 							}
1540 						}
1541 
1542 #if 0 //def DEBUG
1543 						{
1544 							float aim_angle = atan2f(action->aim_position[1] - actors_list[i]->y_pos,
1545 													 action->aim_position[0] - actors_list[i]->x_pos);
1546 							float fire_angle = atan2f(action->fire_position[1] - actors_list[i]->y_pos,
1547 													  action->fire_position[0] - actors_list[i]->x_pos);
1548 							if (aim_angle < 0.0) aim_angle += 2*M_PI;
1549 							if (fire_angle < 0.0) fire_angle += 2*M_PI;
1550 							if (fabs(fire_angle - aim_angle) > M_PI/8.0) {
1551 								char msg[512];
1552 								sprintf(msg,
1553 										"%s (%d): WARNING! Target position is too different from aim position: pos=(%f,%f,%f) aim=(%f,%f,%f) target=(%f,%f,%f) aim_angle=%f target_angle=%f",
1554 										actors_list[i]->actor_name,
1555 										actors_list[i]->actor_id,
1556 										actors_list[i]->x_pos,
1557 										actors_list[i]->y_pos,
1558 										actors_list[i]->z_pos,
1559 										action->aim_position[0],
1560 										action->aim_position[1],
1561 										action->aim_position[2],
1562 										action->fire_position[0],
1563 										action->fire_position[1],
1564 										action->fire_position[2],
1565 										aim_angle, fire_angle);
1566 								LOG_TO_CONSOLE(c_red2, msg);
1567 								missiles_log_message(msg);
1568 							}
1569 						}
1570 #endif // DEBUG
1571 
1572 						missiles_fire_arrow(actors_list[i], action->fire_position, action->shot_type);
1573 						missiles_log_message("%s (%d): cleaning the queue from aim_mode_fire command (end)",
1574 											 actors_list[i]->actor_name, actors_list[i]->actor_id);
1575 						missiles_clean_range_actions_queue(actors_list[i]);
1576 					}
1577 					break;
1578 
1579 /* 				case missile_miss: */
1580 /* 					missiles_log_message("%s (%d): will miss his target", actors_list[i]->actor_name, actors_list[i]->actor_id); */
1581 /* 					if (actors_list[i]->shots_count < MAX_SHOTS_QUEUE) */
1582 /* 						actors_list[i]->shot_type[actors_list[i]->shots_count] = MISSED_SHOT; */
1583 /*  					no_action = 1; */
1584 /* 					break; */
1585 
1586 /* 				case missile_critical: */
1587 /* 					missiles_log_message("%s (%d): will do a critical hit", actors_list[i]->actor_name, actors_list[i]->actor_id); */
1588 /* 					if (actors_list[i]->shots_count < MAX_SHOTS_QUEUE) */
1589 /* 						actors_list[i]->shot_type[actors_list[i]->shots_count] = CRITICAL_SHOT; */
1590 /*  					no_action = 1; */
1591 /* 					break; */
1592 
1593 /* 				case unwear_bow: */
1594 /* 					unwear_item_from_actor(actors_list[i]->actor_id, KIND_OF_WEAPON); */
1595 /*  					no_action = 1; */
1596 /* 					break; */
1597 
1598 /* 				case unwear_quiver: */
1599 /* 					unwear_item_from_actor(actors_list[i]->actor_id, KIND_OF_SHIELD); */
1600 /*  					no_action = 1; */
1601 /* 					break; */
1602 					case wait_cmd:
1603 						//horse only
1604 						ACTOR(i)->stand_idle=1;
1605 					continue;
1606 
1607 					//ok, now the movement, this is the tricky part
1608 					default:
1609 						if(actors_list[i]->que[0]>=move_n && actors_list[i]->que[0]<=move_nw) {
1610 							float rotation_angle;
1611 							int dx, dy;
1612 							int step_duration = actors_list[i]->step_duration;
1613 							struct cal_anim *walk_anim;
1614 
1615 							attachment_props *att_props = get_attachment_props_if_held(actors_list[i]);
1616 							if (att_props)
1617 								walk_anim = get_pose_frame(actors_list[i]->actor_type,actors_list[i],EMOTE_MOTION(actors_list[i]),1);
1618 							else
1619 							walk_anim = get_pose_frame(actors_list[i]->actor_type,actors_list[i],EMOTE_MOTION(actors_list[i]),0);
1620 
1621 
1622 
1623 							actors_list[i]->moving=1;
1624 							actors_list[i]->fighting=0;
1625 							if(last_command<move_n || last_command>move_nw){//update the frame name too
1626 								cal_actor_set_anim(i,*walk_anim);
1627 								actors_list[i]->stop_animation=0;
1628 							}
1629 
1630 							if(last_command!=actors_list[i]->que[0]){ //Calculate the rotation
1631 								targeted_z_rot=(actors_list[i]->que[0]-move_n)*45.0f;
1632 								rotation_angle=get_rotation_vector(z_rot,targeted_z_rot);
1633 								actors_list[i]->rotate_z_speed=rotation_angle/360.0;
1634 
1635 								actors_list[i]->rotate_time_left=360;
1636 								actors_list[i]->rotating=1;
1637 							}
1638                             get_motion_vector(actors_list[i]->que[0], &dx, &dy);
1639 
1640 							/* if other move commands are waiting in the queue,
1641 							 * we walk at a speed that is close to the server speed
1642 							 * else we walk at a slightly slower speed to wait next
1643 							 * incoming walking commands */
1644                             if (actors_list[i]->que[1] >= move_n &&
1645                                 actors_list[i]->que[1] <= move_nw) {
1646                                 if (actors_list[i]->que[2] >= move_n &&
1647                                     actors_list[i]->que[2] <= move_nw) {
1648 									if (actors_list[i]->que[3] >= move_n &&
1649 										actors_list[i]->que[3] <= move_nw)
1650 										actors_list[i]->movement_time_left = (int)(step_duration*0.9); // 3 moves
1651 									else
1652 										actors_list[i]->movement_time_left = step_duration; // 2 moves
1653 								}
1654                                 else
1655                                     actors_list[i]->movement_time_left = (int)(step_duration*1.1); // 1 move
1656                             }
1657                             else {
1658                                 actors_list[i]->movement_time_left = (int)(step_duration*1.2); // 0 move
1659                             }
1660 							// if we have a diagonal motion, we slow down the animation a bit
1661 							if (dx != 0 && dy != 0)
1662 								actors_list[i]->movement_time_left = (int)(actors_list[i]->movement_time_left*1.2+0.5);
1663 
1664                             // we compute the moving speeds in x, y and z directions
1665 							actors_list[i]->move_x_speed = 0.5*(dx+actors_list[i]->x_tile_pos)-actors_list[i]->x_pos;
1666 							actors_list[i]->move_y_speed = 0.5*(dy+actors_list[i]->y_tile_pos)-actors_list[i]->y_pos;
1667 							actors_list[i]->move_z_speed = get_tile_height(actors_list[i]->x_tile_pos+dx, actors_list[i]->y_tile_pos+dy) - actors_list[i]->z_pos;
1668 							actors_list[i]->move_x_speed /= (float)actors_list[i]->movement_time_left;
1669 							actors_list[i]->move_y_speed /= (float)actors_list[i]->movement_time_left;
1670 							actors_list[i]->move_z_speed /= (float)actors_list[i]->movement_time_left;
1671 
1672 							/* we change the speed of the walking animation according to the walking speed and to the size of the actor
1673 							 * we suppose here that the normal speed of the walking animation is 2 meters per second (1 tile in 250ms) */
1674 							actors_list[i]->cur_anim.duration_scale = walk_anim->duration_scale;
1675 							actors_list[i]->cur_anim.duration_scale *= (float)DEFAULT_STEP_DURATION/(actors_list[i]->movement_time_left*actors_list[i]->scale);
1676 							if (actors_defs[actor_type].actor_scale != 1.0)
1677 								actors_list[i]->cur_anim.duration_scale /= actors_defs[actor_type].actor_scale;
1678 							else
1679 								actors_list[i]->cur_anim.duration_scale /= actors_defs[actor_type].scale;
1680 							if (dx != 0 && dy != 0)
1681 								actors_list[i]->cur_anim.duration_scale *= 1.4142315;
1682 						} else if(actors_list[i]->que[0]>=turn_n && actors_list[i]->que[0]<=turn_nw) {
1683 							float rotation_angle;
1684 
1685 							int horse_angle=0;
1686 							if(IS_HORSE(i))
1687 								horse_angle=(ACTOR(i)->fighting&&ACTOR_WEAPON(MY_HORSE_ID(i))->turn_horse) ? (HORSE_FIGHT_ROTATION):(0);
1688 							else if(HAS_HORSE(i))
1689 								horse_angle=(ACTOR(i)->fighting&&ACTOR_WEAPON(i)->turn_horse) ? (HORSE_FIGHT_ROTATION):(0);
1690 
1691 							if((HAS_HORSE(i)||IS_HORSE(i))&&(ACTOR(i)->in_aim_mode||MY_HORSE(i)->in_aim_mode)) {
1692 								horse_angle=HORSE_RANGE_ROTATION;
1693 								ACTOR(i)->stand_idle=1;
1694 								//if(actors_list[i]->actor_id==yourself) printf("%i, %s rotates\n",thecount, ACTOR(i)->actor_name);
1695 								//if(MY_HORSE(i)->actor_id==yourself) printf("%i, Horse %s rotates\n",thecount, MY_HORSE(i)->actor_name);
1696 							}
1697 							targeted_z_rot=(ACTOR(i)->que[0]-turn_n)*45.0f-horse_angle;
1698 							rotation_angle=get_rotation_vector(ACTOR(i)->z_rot,targeted_z_rot);
1699 							ACTOR(i)->rotate_z_speed=rotation_angle/360.0f;
1700 							ACTOR(i)->rotate_time_left=360;
1701 							ACTOR(i)->rotating=1;
1702 							ACTOR(i)->stop_animation=1;
1703 
1704 							if(ACTOR(i)->fighting&&horse_angle!=0) ACTOR(i)->horse_rotated=1;
1705 							missiles_log_message("%s (%d): rotation %d requested", actors_list[i]->actor_name, actors_list[i]->actor_id, actors_list[i]->que[0] - turn_n);
1706 						}
1707 					}
1708 
1709 					//mark the actor as being busy
1710 					if (!no_action)
1711 						actors_list[i]->busy=1;
1712 					else if(HAS_HORSE(i)) ACTOR(i)->in_aim_mode=3; //needed to unfreeze the horse in move_to_next_frame
1713 					//if (actors_list[i]->actor_id==yourself) LOG_TO_CONSOLE(c_green2,"Busy");
1714 					//save the last command. It is especially good for run and walk
1715 					actors_list[i]->last_command=actors_list[i]->que[0];
1716 
1717 					/* We do the enter in aim mode in two steps in order the actor have
1718 					 * the time to do the load animation before rotating bones. This is
1719 					 * necessary in the case of cross bows where the actor need to use
1720 					 * his foot to reload. So here, we don't remove the enter aim mode
1721 					 * from the queue in order to treat it again but this time in aim mode.
1722 					 */
1723 					if (actors_list[i]->que[0] == enter_aim_mode && actors_list[i]->in_aim_mode == 0) {
1724 						actors_list[i]->in_aim_mode = 1;
1725 						actors_list[i]->last_command=missile_miss; //dirty hack to avoid processing enter_aim_mode twice :/
1726 						continue;
1727 					}
1728 					unqueue_cmd(i);
1729 				}
1730 			}
1731 		}
1732 }
1733 
free_actor_data(int actor_index)1734 void free_actor_data(int actor_index)
1735 {
1736 	actor *act = actors_list[actor_index];
1737 	if(act->calmodel!=NULL)
1738 		model_delete(act->calmodel);
1739 	if(act->remapped_colors)
1740 	{
1741 		free_actor_texture(act->texture_id);
1742 	}
1743 	if (act->is_enhanced_model)
1744 	{
1745 		free_actor_texture(act->texture_id);
1746 		if (act->body_parts)
1747 		{
1748 			free(act->body_parts);
1749 		}
1750 	}
1751 #ifdef NEW_SOUND
1752     stop_sound(act->cur_anim_sound_cookie);
1753     act->cur_anim_sound_cookie = 0;
1754 #endif	//NEW_SOUND
1755     ec_actor_delete(act);
1756 }
1757 
1758 //  Assumed LOCK_ACTORS_LISTS mutex already held
destroy_actor_common(size_t actor_list_index)1759 static void destroy_actor_common(size_t actor_list_index)
1760 {
1761 	if ((actor_list_index >= max_actors) || (actors_list[actor_list_index] == NULL))
1762 		return; // return of not valid actor
1763 	free_actor_special_effect(actors_list[actor_list_index]->actor_id);
1764 	free_actor_data(actor_list_index);
1765 	free(actors_list[actor_list_index]);
1766 	actors_list[actor_list_index]=NULL;
1767 }
1768 
destroy_actor(int actor_id)1769 void destroy_actor(int actor_id)
1770 {
1771 	int i;
1772     int attached_actor = -1;
1773 
1774 #ifdef EXTRA_DEBUG
1775 	ERR();
1776 #endif
1777 	for(i=0;i<max_actors;i++){
1778 		if(actors_list[i])//The timer thread doesn't free memory
1779 			if(actors_list[i]->actor_id==actor_id){
1780 				LOCK_ACTORS_LISTS();
1781                 attached_actor = actors_list[i]->attached_actor;
1782 
1783 				if (actor_id == yourself)
1784 					set_our_actor (NULL);
1785 				destroy_actor_common(i);
1786 				if(i==max_actors-1)max_actors--;
1787 				else {
1788 					//copy the last one down and fill in the hole
1789 					max_actors--;
1790 					actors_list[i]=actors_list[max_actors];
1791 					actors_list[max_actors]=NULL;
1792                     if (attached_actor == max_actors) attached_actor = i;
1793 					if (actors_list[i] && actors_list[i]->attached_actor >= 0)
1794 						actors_list[actors_list[i]->attached_actor]->attached_actor = i;
1795 				}
1796 
1797                 if (attached_actor >= 0)
1798                 {
1799                     destroy_actor_common(attached_actor);
1800                     if(attached_actor==max_actors-1)max_actors--;
1801                     else {
1802                         //copy the last one down and fill in the hole
1803                         max_actors--;
1804                         actors_list[attached_actor]=actors_list[max_actors];
1805                         actors_list[max_actors]=NULL;
1806 						if (actors_list[attached_actor] && actors_list[attached_actor]->attached_actor >= 0)
1807 							actors_list[actors_list[attached_actor]->attached_actor]->attached_actor = attached_actor;
1808                     }
1809                 }
1810 
1811 				actor_under_mouse = NULL;
1812 				UNLOCK_ACTORS_LISTS();
1813 				break;
1814 			}
1815 	}
1816 }
1817 
destroy_all_actors()1818 void destroy_all_actors()
1819 {
1820 	int i=0;
1821 	LOCK_ACTORS_LISTS();	//lock it to avoid timing issues
1822 	set_our_actor (NULL);
1823 	for(i=0;i<max_actors;i++) {
1824 		if(actors_list[i]){
1825 			destroy_actor_common(i);
1826 		}
1827 	}
1828 	max_actors= 0;
1829 	actor_under_mouse = NULL;
1830 	my_timer_adjust= 0;
1831 	harvesting_effect_reference = NULL;
1832 	UNLOCK_ACTORS_LISTS();	//unlock it since we are done
1833 }
1834 
1835 
1836 
1837 
update_all_actors(int log_the_update)1838 void update_all_actors(int log_the_update)
1839 {
1840  	Uint8 str[40];
1841 
1842 	//we got a nasty error, log it
1843 	if (log_the_update)
1844 		LOG_TO_CONSOLE(c_red2,resync_server);
1845 
1846 	destroy_all_actors();
1847 	str[0]=SEND_ME_MY_ACTORS;
1848 	my_tcp_send(my_socket,str,1);
1849 }
1850 
push_command_in_actor_queue(unsigned int command,actor * act)1851 int push_command_in_actor_queue(unsigned int command, actor *act)
1852 {
1853 	int k;
1854 	for(k=0;k<MAX_CMD_QUEUE;k++){
1855 		if(act->que[k]==nothing){
1856 			//if we are SEVERLY behind, just update all the actors in range
1857 			if(k>MAX_CMD_QUEUE-2) break;
1858 			else if(k>MAX_CMD_QUEUE-8){
1859 				// is the front a sit/stand spam?
1860 				if((act->que[0]==stand_up||act->que[0]==sit_down)
1861 				   &&(act->que[1]==stand_up||act->que[1]==sit_down)){
1862 					int j;
1863 					//move que down with one command
1864 					for(j=0;j<=k;j++){
1865 						act->que[j]=act->que[j+1];
1866 					}
1867 					act->que[j]=nothing;
1868 					//backup one entry
1869 					k--;
1870 				}
1871 
1872 				// is the end a sit/stand spam?
1873 				else if((command==stand_up||command==sit_down)
1874 						&& (act->que[k-1]==stand_up||act->que[k-1]==sit_down)) {
1875 					act->que[k-1]=command;
1876 					break;
1877 				}
1878 
1879 			}
1880 
1881 			act->que[k]=command;
1882 			break;
1883 		}
1884 	}
1885 	return k;
1886 }
1887 
1888 
sanitize_cmd_queue(actor * act)1889 void sanitize_cmd_queue(actor *act){
1890 	int k,j;
1891 	for(k=0,j=0;k<MAX_CMD_QUEUE-1-j;k++){
1892 		if(act->que[k]==nothing) j++;
1893 		act->que[k]=act->que[k+j];
1894 	}
1895 	for(k=MAX_CMD_QUEUE-1;k>0&&j>0;k--,j--) act->que[k]=nothing;
1896 }
1897 
add_command_to_actor(int actor_id,unsigned char command)1898 void add_command_to_actor(int actor_id, unsigned char command)
1899 {
1900 	//int i=0;
1901 	int k=0;
1902 	int k2 = 0;
1903 	//int have_actor=0;
1904 //if ((actor_id==yourself)&&(command==enter_combat)) LOG_TO_CONSOLE(c_green2,"FIGHT!");
1905 	actor * act;
1906 	int isme = 0;
1907 #ifdef EXTRA_DEBUG
1908 	ERR();
1909 #endif
1910 	LOCK_ACTORS_LISTS();
1911 	act= get_actor_ptr_from_id(actor_id);
1912 
1913 	if(!act){
1914 		//Resync
1915 		//if we got here, it means we don't have this actor, so get it from the server...
1916 		LOG_ERROR("%s %d - %d\n", cant_add_command, command, actor_id);
1917 	} else {
1918 
1919 		//if (get_our_actor()->actor_id==act->actor_id) printf("ADD COMMAND %i to %i\n",command,actor_id);
1920 
1921 		if (command == missile_miss) {
1922 			missiles_log_message("%s (%d): will miss his target", act->actor_name, actor_id);
1923 			if (act->range_actions_count <= MAX_RANGE_ACTION_QUEUE &&
1924 				act->range_actions_count > 0)
1925 				act->range_actions[act->range_actions_count-1].shot_type = MISSED_SHOT;
1926 			else
1927 				LOG_ERROR("%s (%d): unable to add a missed shot action, the queue is empty!", act->actor_name, actor_id);
1928 			UNLOCK_ACTORS_LISTS();
1929 			return;
1930 		}
1931 		else if (command == missile_critical) {
1932 			missiles_log_message("%s (%d): will do a critical hit", act->actor_name, actor_id);
1933 			if (act->range_actions_count <= MAX_RANGE_ACTION_QUEUE &&
1934 				act->range_actions_count > 0)
1935 				act->range_actions[act->range_actions_count-1].shot_type = CRITICAL_SHOT;
1936 			else
1937 				LOG_ERROR("%s (%d): unable to add a critical shot action, the queue is empty!", act->actor_name, actor_id);
1938 			UNLOCK_ACTORS_LISTS();
1939 			return;
1940 		}
1941 		else if (command == aim_mode_reload) {
1942 			missiles_log_message("%s (%d): reload after next fire", act->actor_name, actor_id);
1943 			if (act->range_actions_count <= MAX_RANGE_ACTION_QUEUE &&
1944 				act->range_actions_count > 0)
1945 				act->range_actions[act->range_actions_count-1].reload = 1;
1946 			else
1947 				LOG_ERROR("%s (%d): unable to add a reload action, the queue is empty!", act->actor_name, actor_id);
1948 			UNLOCK_ACTORS_LISTS();
1949 			return;
1950 		}
1951 		else if (command == enter_aim_mode)
1952 		{
1953 			missiles_log_message("%s (%d): adding enter_aim_mode command",
1954 								 act->actor_name, act->actor_id);
1955 		}
1956 		else if (command == leave_aim_mode)
1957 		{
1958 			missiles_log_message("%s (%d): adding leave_aim_mode command",
1959 								 act->actor_name, act->actor_id);
1960 		}
1961 
1962 
1963 		if(command==leave_combat||command==enter_combat||command==die1||command==die2)
1964 		{
1965 			int j= 0;
1966 
1967 			//Strip the queue for attack messages
1968 			for(k=0; k<MAX_CMD_QUEUE; k++){
1969 				switch(act->que[k]){
1970 					case pain1:
1971 					case pain2:
1972 					case attack_up_1:
1973 					case attack_up_2:
1974 					case attack_up_3:
1975 					case attack_up_4:
1976 					case attack_down_1:
1977 					case attack_down_2:
1978 						act->que[k]= nothing;
1979 						break;
1980 
1981 					default:
1982 						act->que[j]= act->que[k];
1983 						j++;
1984 						if(j<=k){
1985 							act->que[k]= nothing;
1986 						}
1987 						break;
1988 				}
1989 			}
1990 
1991 			if(act->attached_actor>=0) {
1992 				//strip horse queue too
1993 				int j=0;
1994 				actor *horse=actors_list[act->attached_actor];
1995 
1996 			for(k=0; k<MAX_CMD_QUEUE; k++){
1997 				switch(horse->que[k]){
1998 					case pain1:
1999 					case pain2:
2000 					case attack_up_1:
2001 					case attack_up_2:
2002 					case attack_up_3:
2003 					case attack_up_4:
2004 					case attack_down_1:
2005 					case attack_down_2:
2006 						horse->que[k]= nothing;
2007 						break;
2008 
2009 					default:
2010 						horse->que[j]= horse->que[k];
2011 						j++;
2012 						if(j<=k){
2013 							horse->que[k]= nothing;
2014 						}
2015 						break;
2016 				}
2017 			}
2018 			}
2019 
2020 
2021 
2022 			if(act->last_command == nothing)
2023 			{
2024 				//We may be on idle, update the actor so we can reduce the rendering lag
2025 				CalModel_Update(act->calmodel, 5.0f);
2026 				build_actor_bounding_box(act);
2027 				missiles_rotate_actor_bones(get_actor_ptr_from_id(actor_id));
2028 				if (use_animation_program)
2029 				{
2030 					set_transformation_buffers(act);
2031 				}
2032 			}
2033 		}
2034 
2035 		k = push_command_in_actor_queue(command, act);
2036 
2037 		if (act->attached_actor >= 0){
2038 			//if in aim mode, ignore turning and ranging related commands. We do it manually in next_command()
2039 			switch(command){
2040 				case enter_aim_mode:
2041 				case leave_aim_mode:
2042 				case enter_combat:
2043 				case leave_combat:
2044 				case aim_mode_fire:
2045 					//insert a wait_cmd where the horse must synch with the actor
2046 					k2 = push_command_in_actor_queue(wait_cmd, actors_list[act->attached_actor]);
2047 					break;
2048 				default:
2049 					k2 = push_command_in_actor_queue(command, actors_list[act->attached_actor]);
2050 			}
2051 		}
2052 		else
2053 			k2 = k;
2054 		{
2055 			actor * me = get_our_actor();
2056 			if (me!=NULL)
2057 				isme = act->actor_id == me->actor_id;
2058 		}
2059 
2060 
2061 		//if(act->actor_id==yourself) printf("COMMAND: %i at pos %i (and %i)\n",command,k,k2);
2062 		//if(act->actor_id==yourself) print_queue(act);
2063 		//Reduce resync in invasions
2064 		if(command==enter_combat) {
2065 			// we received an enter_combat, look back in the queue
2066 			// if a leave_combat is found and all the commands in between
2067 			// are turning commands, just ignore the leave and the enter combat commands
2068 
2069 			int j=k-1;
2070 			int j2=k2-1;
2071 			while(act->que[j]>=turn_n&&act->que[j]<=turn_nw&&j>=0) j--; //skip rotations
2072 			if (act->attached_actor >= 0)
2073 				while(actors_list[act->attached_actor]->que[j2]>=turn_n
2074 					&&actors_list[act->attached_actor]->que[j2]<=turn_nw
2075 					&&j2>=0) j2--; //skip rotations for horse
2076 			if(j>=0&&act->que[j]==leave_combat) {
2077 				//remove leave_combat and enter_combat
2078 				act->que[j]=nothing;
2079 				act->que[k]=nothing;
2080 				sanitize_cmd_queue(act);
2081 				//if(act->actor_id==yourself) printf("   actor %s: skipped %i and %i\n",act->actor_name,j,k);
2082 				if(act->attached_actor >=0&&j2>=0&&actors_list[act->attached_actor]->que[j2]==wait_cmd) {
2083 					//remove leave_combat and enter_combat for horse
2084 					actors_list[act->attached_actor]->que[j2]=nothing;
2085 					actors_list[act->attached_actor]->que[k2]=nothing;
2086 					sanitize_cmd_queue(actors_list[act->attached_actor]);
2087 					//if(act->actor_id==yourself) printf("   horse %s: skipped %i and %i\n",act->actor_name,j2,k2);
2088 				}
2089 			}
2090 
2091 			//if(act->actor_id==yourself) printf("   ***Skip Done***\n");
2092 			//if(act->actor_id==yourself) print_queue(act);
2093 		}
2094 
2095 
2096 
2097 
2098 		switch(command) {
2099 		case enter_combat:
2100 			act->async_fighting= 1;
2101 			check_to_auto_disable_ranging_lock();
2102 			break;
2103 		case leave_combat:
2104 			act->async_fighting= 0;
2105 			break;
2106 		case move_n:
2107 		case run_n:
2108 			act->async_y_tile_pos++;
2109 			act->async_z_rot= 0;
2110 			if(isme && pf_follow_path)
2111 			{
2112                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2113                     pf_destroy_path();
2114             }
2115 			break;
2116 		case move_ne:
2117 		case run_ne:
2118 			act->async_x_tile_pos++;
2119 			act->async_y_tile_pos++;
2120 			act->async_z_rot= 45;
2121 			if(isme && pf_follow_path)
2122 			{
2123                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2124                     pf_destroy_path();
2125             }
2126 			break;
2127 		case move_e:
2128 		case run_e:
2129 			act->async_x_tile_pos++;
2130 			act->async_z_rot= 90;
2131 			if(isme && pf_follow_path)
2132 			{
2133                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2134                     pf_destroy_path();
2135             }
2136 			break;
2137 		case move_se:
2138 		case run_se:
2139 			act->async_x_tile_pos++;
2140 			act->async_y_tile_pos--;
2141 			act->async_z_rot= 135;
2142 			if(isme && pf_follow_path)
2143 			{
2144                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2145                     pf_destroy_path();
2146             }
2147 			break;
2148 		case move_s:
2149 		case run_s:
2150 			act->async_y_tile_pos--;
2151 			act->async_z_rot= 180;
2152 			if(isme && pf_follow_path)
2153 			{
2154                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2155                     pf_destroy_path();
2156             }
2157 			break;
2158 		case move_sw:
2159 		case run_sw:
2160 			act->async_x_tile_pos--;
2161 			act->async_y_tile_pos--;
2162 			act->async_z_rot= 225;
2163 			if(isme && pf_follow_path)
2164 			{
2165                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2166                     pf_destroy_path();
2167             }
2168 			break;
2169 		case move_w:
2170 		case run_w:
2171 			act->async_x_tile_pos--;
2172 			act->async_z_rot= 270;
2173 			if(isme && pf_follow_path)
2174 			{
2175                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2176                     pf_destroy_path();
2177             }
2178 			break;
2179 		case move_nw:
2180 		case run_nw:
2181 			act->async_x_tile_pos--;
2182 			act->async_y_tile_pos++;
2183 			act->async_z_rot= 315;
2184 			if(isme && pf_follow_path)
2185 			{
2186                 if(checkvisitedlist(act->async_x_tile_pos,act->async_y_tile_pos))
2187                     pf_destroy_path();
2188             }
2189 			break;
2190 		case turn_n:
2191 		case turn_ne:
2192 		case turn_e:
2193 		case turn_se:
2194 		case turn_s:
2195 		case turn_sw:
2196 		case turn_w:
2197 		case turn_nw:
2198 			 act->async_z_rot= (command-turn_n)*45;
2199 			 break;
2200 		}
2201 
2202 		if (k != k2) {
2203 			LOG_ERROR("Inconsistency between queues of attached actors %s (%d) and %s (%d)!",
2204 					  act->actor_name,
2205 					  act->actor_id,
2206 					  actors_list[act->attached_actor]->actor_name,
2207 					  actors_list[act->attached_actor]->actor_id);
2208 		}
2209 		else
2210 		if(k>MAX_CMD_QUEUE-2){
2211 			int i;
2212 			int k;
2213 			if (max_fps == limit_fps)
2214 				LOG_ERROR("Too much commands in the queue for actor %d (%s) => skip emotes!",
2215 					  act->actor_id, act->actor_name);
2216 			for(i=MAX_CMD_QUEUE-1;i>=0;i--) {
2217 				if(act->que[i]>=emote_cmd&&act->que[i]<wait_cmd) {
2218 					//skip this emote
2219 					for(k=i;k<MAX_CMD_QUEUE-1;k++) {
2220 						act->que[k]=act->que[k+1];
2221 						if(act->attached_actor>=0)
2222 						actors_list[act->attached_actor]->que[k]=actors_list[act->attached_actor]->que[k+1];
2223 					}
2224 					act->que[k]=nothing;
2225 					actors_list[act->attached_actor]->que[k]=nothing;
2226 					add_command_to_actor(actor_id,command); //RECURSIVE!!!! should be done only one time
2227 					UNLOCK_ACTORS_LISTS();
2228 					return;
2229 				}
2230 			}
2231 			//if we are here no emotes have been skipped
2232 			if (max_fps == limit_fps)
2233 			{
2234 				LOG_ERROR("Too much commands in the queue for actor %d (%s) => resync!\n",
2235 					act->actor_id, act->actor_name);
2236 #ifdef	ANIMATION_SCALING
2237 				LOG_ERROR("animation_scale: %f\n", act->animation_scale);
2238 #endif	/* ANIMATION_SCALING */
2239 				for (i = 0; i < MAX_CMD_QUEUE; ++i)
2240 					LOG_ERROR("%dth command in the queue: %d\n", i, (int)act->que[i]);
2241 			}
2242 			update_all_actors(max_fps == limit_fps);
2243 		}
2244 	}
2245 	UNLOCK_ACTORS_LISTS();
2246 }
2247 
2248 
queue_emote(actor * act,emote_data * emote)2249 void queue_emote(actor *act, emote_data *emote){
2250 	int j,k;
2251 
2252 	for (k = 0; k < MAX_EMOTE_QUEUE; k++) {
2253 		if (act->emote_que[k].origin!=SERVER_EMOTE) {
2254 			if (k <= MAX_EMOTE_QUEUE - 2) {
2255 				for(j=MAX_EMOTE_QUEUE-1;j>k;j--) //throw away last client_emote if necessary
2256 					act->emote_que[j]=act->emote_que[j-1];
2257 				act->emote_que[k].emote = emote;
2258 				act->emote_que[k].origin = SERVER_EMOTE;
2259 				act->emote_que[k].create_time = cur_time;
2260 				//printf("in queue SERVER: %p at %i in %i\n\n",emote,cur_time,k);
2261 			}
2262 			break;
2263 		}
2264 	}
2265 	if (k > MAX_EMOTE_QUEUE - 2)
2266 		LOG_ERROR("Too many commands in the emote queue for actor %d (%s)", act->actor_id, act->actor_name);
2267 
2268 
2269 }
2270 
add_emote_to_actor(int actor_id,int emote_id)2271 void add_emote_to_actor(int actor_id, int emote_id){
2272 
2273 	actor *act;
2274 	emote_data *emote;
2275 	hash_entry *he;
2276 
2277 	LOCK_ACTORS_LISTS();
2278 	act=get_actor_ptr_from_id(actor_id);
2279 
2280 	//printf("SERVER MSG\nwe have actor %i %p\n",actor_id,act);
2281 	if(emote_id!=0) {
2282 		//dirty, but avoids warnings :P
2283 		he=hash_get(emotes, (void *)(uintptr_t)emote_id);
2284 		if(!he) {
2285 			LOG_ERROR("%s (Emote) %i- NULL emote passed", cant_add_command,emote_id);
2286 			UNLOCK_ACTORS_LISTS();
2287 			return;
2288 		}
2289 		emote = he->item;
2290 		/*if(emote->pose<=EMOTE_STANDING){
2291 			//we have a pose, set it and return
2292 			//printf("setting pose %i (%i) for actor %s\n",emote->id,emote->pose,act->actor_name);
2293 			act->poses[emote->pose]=emote;
2294 			//force set_idle
2295 			if(emote->pose==EMOTE_SITTING) act->sit_idle=0;
2296 			if(emote->pose==EMOTE_STANDING) act->stand_idle=0;
2297 			UNLOCK_ACTORS_LISTS();
2298 			return;
2299 		}*/
2300 	} else emote=NULL;
2301 
2302 	//printf("emote message to be added %p\n",emote);
2303 	if (!act) {
2304 		LOG_ERROR("%s (Emote) %d - NULL actor passed", cant_add_command, emote);
2305 	} else {
2306 		queue_emote(act,emote);
2307 	}
2308 	UNLOCK_ACTORS_LISTS();
2309 
2310 }
2311 
2312 
2313 
get_actor_damage(int actor_id,int damage)2314 void get_actor_damage(int actor_id, int damage)
2315 {
2316 	//int i=0;
2317 	actor * act;
2318 	float blood_level;
2319 	float bone_list[1024][3];
2320 	int total_bones;
2321 	int bone;
2322 	float bone_x, bone_y, bone_z;
2323 
2324 #ifdef EXTRA_DEBUG
2325 	ERR();
2326 #endif
2327 	act = get_actor_ptr_from_id(actor_id);
2328 
2329 	if(!act){
2330 		//if we got here, it means we don't have this actor, so get it from the server...
2331 	} else {
2332 		if(floatingmessages_enabled){
2333 			act->last_health_loss=cur_time;
2334 		}
2335 
2336 		if (actor_id == yourself)
2337 			set_last_damage(damage);
2338 
2339 		act->damage=damage;
2340 		act->damage_ms=2000;
2341 		if(act->cur_health > (Uint16)damage)
2342 			act->cur_health -= damage;
2343 		else
2344 			act->cur_health = 0;
2345 
2346 		if (act->cur_health <= 0) {
2347 #ifdef NEW_SOUND
2348 			add_death_sound(act);
2349 #endif // NEW_SOUND
2350 			increment_death_counter(act);
2351 		}
2352 		act->last_range_attacker_id = -1;
2353 
2354 		if (use_eye_candy && enable_blood)
2355 		{
2356 			if (strcmp(act->actor_name, "Gargoyle") && strcmp(act->actor_name, "Skeleton") && strcmp(act->actor_name, "Phantom Warrior"))	//Ideally, we'd also check to see if it was a player or not, but since this is just cosmetic...
2357 			{
2358 				blood_level=(int)powf(damage / powf(act->max_health, 0.5), 0.75) + 0.5;
2359 				total_bones = CalSkeleton_GetBonePoints(CalModel_GetSkeleton(act->calmodel), &bone_list[0][0]);
2360 				bone = rand() % total_bones;
2361 				bone_x = bone_list[bone][0] + act->x_pos + 0.25;
2362 				bone_y = bone_list[bone][1] + act->y_pos + 0.25;
2363 				bone_z = bone_list[bone][2] + ec_get_z(act);
2364 //				printf("ec_create_impact_blood((%f %f, %f), (%f, %f, %f), %d, %f);", bone_x, bone_y, bone_z, ((float)rand()) * blood_level / RAND_MAX / 13.0, ((float)rand()) * blood_level / RAND_MAX / 13.0, ((float)rand()) * blood_level / RAND_MAX / 13.0, (poor_man ? 6 : 10), blood_level);
2365 				ec_create_impact_blood(bone_x, bone_y, bone_z, (float)rand() * blood_level / (RAND_MAX * 13.0), (float)rand() * blood_level / (RAND_MAX * 13.0), (float)rand() * blood_level / (RAND_MAX * 13.0), (poor_man ? 6 : 10), blood_level);
2366 			}
2367 		}
2368 	}
2369 }
2370 
get_actor_heal(int actor_id,int quantity)2371 void get_actor_heal(int actor_id, int quantity)
2372 {
2373 	actor *act;
2374 #ifdef EXTRA_DEBUG
2375 	ERR();
2376 #endif
2377 	act = get_actor_ptr_from_id(actor_id);
2378 
2379 	if(!act){
2380 		//if we got here, it means we don't have this actor, so get it from the server...
2381 	} else {
2382 
2383 		if (actor_id == yourself)
2384 			set_last_heal(quantity);
2385 
2386 		if(floatingmessages_enabled){
2387 			act->damage=-quantity;
2388 			act->damage_ms=2000;
2389 			act->last_health_loss=cur_time;
2390 		}
2391 
2392 		act->cur_health+=quantity;
2393 	}
2394 	//if we got here, it means we don't have this actor, so get it from the server...
2395 }
2396 
get_actor_health(int actor_id,int quantity)2397 void get_actor_health(int actor_id, int quantity)
2398 {
2399 	//int i=0;
2400 	actor *act;
2401 #ifdef EXTRA_DEBUG
2402 	ERR();
2403 #endif
2404 	act = get_actor_ptr_from_id(actor_id);
2405 
2406 	if(!act){
2407 		//if we got here, it means we don't have this actor, so get it from the server...
2408 	} else {
2409 //		if(floatingmessages_enabled){
2410 			//act->damage=-quantity;
2411 			//act->damage_ms=2000;
2412 			//act->last_health_loss=cur_time;
2413 //		}
2414 
2415 		act->max_health=quantity;
2416 	}
2417 	//if we got here, it means we don't have this actor, so get it from the server...
2418 }
2419 
move_self_forward()2420 void move_self_forward()
2421 {
2422 	int x,y,rot,tx,ty;
2423 
2424 	actor *me = get_our_actor ();
2425 
2426 	if(!me)return;//Wtf!?
2427 
2428 	x=me->x_tile_pos;
2429 	y=me->y_tile_pos;
2430 	rot=(int)rint(me->z_rot/45.0f);
2431 	if (rot < 0) rot += 8;
2432 	switch(rot) {
2433 		case 8: //360
2434 		case 0: //0
2435 			tx=x;
2436 			ty=y+1;
2437 			break;
2438 		case 1: //45
2439 			tx=x+1;
2440 			ty=y+1;
2441 			break;
2442 		case 2: //90
2443 			tx=x+1;
2444 			ty=y;
2445 			break;
2446 		case 3: //135
2447 			tx=x+1;
2448 			ty=y-1;
2449 			break;
2450 		case 4: //180
2451 			tx=x;
2452 			ty=y-1;
2453 			break;
2454 		case 5: //225
2455 			tx=x-1;
2456 			ty=y-1;
2457 			break;
2458 		case 6: //270
2459 			tx=x-1;
2460 			ty=y;
2461 			break;
2462 		case 7: //315
2463 			tx=x-1;
2464 			ty=y+1;
2465 			break;
2466 		default:
2467 			tx=x;
2468 			ty=y;
2469 	}
2470 
2471 	//check to see if the coordinates are OUTSIDE the map
2472 	if(ty<0 || tx<0 || tx>=tile_map_size_x*6 || ty>=tile_map_size_y*6) {
2473 		return;
2474 	}
2475 	if (pf_follow_path) {
2476 		pf_destroy_path();
2477 	}
2478 
2479 	move_to (tx, ty, 0);
2480 }
2481 
2482 
actor_check_string(actor_types * act,const char * section,const char * type,const char * value)2483 void actor_check_string(actor_types *act, const char *section, const char *type, const char *value)
2484 {
2485 	if (value == NULL || *value=='\0')
2486 	{
2487 #ifdef DEBUG
2488 		LOG_ERROR("Data Error in %s(%d): Missing %s.%s", act->actor_name, act->actor_type, section, type);
2489 #endif // DEBUG
2490 	}
2491 }
2492 
actor_check_int(actor_types * act,const char * section,const char * type,int value)2493 void actor_check_int(actor_types *act, const char *section, const char *type, int value)
2494 {
2495 	if (value < 0)
2496 	{
2497 #ifdef DEBUG
2498 		LOG_ERROR("Data Error in %s(%d): Missing %s.%s", act->actor_name, act->actor_type, section, type);
2499 #endif // DEBUG
2500 	}
2501 }
2502 
2503 
2504 
add_emote_to_dict(const xmlNode * node,emote_data * emote)2505 void add_emote_to_dict(const xmlNode *node, emote_data *emote)
2506 {
2507 	emote_dict *entry=NULL;
2508 	if(!emote_cmds)
2509 		emote_cmds= create_hash_table(EMOTE_CMDS_HASH,hash_fn_str,cmp_fn_str,free);
2510 
2511 	entry = (emote_dict*) malloc(sizeof(emote_dict));
2512 	get_string_value (entry->command, sizeof(entry->command), node);
2513 	entry->emote = emote;
2514 	hash_add(emote_cmds,(void*)entry->command,(void*)entry);
2515 	//printf("Adding Emote Command: [%s], emote %p\n",entry->command,entry->emote);
2516 
2517 }
2518 
init_emote(emote_data * emote)2519 void init_emote(emote_data *emote){
2520 	int i;
2521 
2522 	emote->timeout=EMOTE_TIMEOUT;
2523 	emote->barehanded=0;
2524 	for(i=0;i<EMOTE_ACTOR_TYPES;i++){
2525 		emote->anims[i][EMOTE_SITTING][0]=emote->anims[i][EMOTE_SITTING][1]=NULL;
2526 		emote->anims[i][EMOTE_WALKING][0]=emote->anims[i][EMOTE_WALKING][1]=NULL;
2527 		emote->anims[i][EMOTE_RUNNING][0]=emote->anims[i][EMOTE_RUNNING][1]=NULL;
2528 		emote->anims[i][EMOTE_STANDING][0]=emote->anims[i][EMOTE_STANDING][1]=NULL;
2529 	}
2530 	emote->name[0]=0;
2531 	emote->desc[0]=0;
2532 }
2533 
2534 
2535 // 0=f 1=m <0=any, race 0=human, 1=elf, 2=dwarf, 3=orchan, 4=gnome, 5=draegoni, 6=monster
calc_actor_types(int sex,int race,int * buf,int * len)2536 void calc_actor_types(int sex, int race, int *buf, int *len){
2537 
2538 	buf[0]=emote_actor_type(human_female);
2539 	buf[1]=emote_actor_type(human_male);
2540 	buf[2]=emote_actor_type(elf_female);
2541 	buf[3]=emote_actor_type(elf_male);
2542 	buf[4]=emote_actor_type(dwarf_female);
2543 	buf[5]=emote_actor_type(dwarf_male);
2544 	buf[6]=emote_actor_type(orchan_female);
2545 	buf[7]=emote_actor_type(orchan_male);
2546 	buf[8]=emote_actor_type(gnome_female);
2547 	buf[9]=emote_actor_type(gnome_male);
2548 	buf[10]=emote_actor_type(draegoni_female);
2549 	buf[11]=emote_actor_type(draegoni_male);
2550 	buf[12]=emote_actor_type(-1); //all other mobs
2551 	buf[13]=emote_actor_type(-1); //all other mobs
2552 
2553 
2554 	if(sex<0&&race<0){
2555 		*len=14;
2556 	} else if (sex<0) {
2557 		*len=2;
2558 		buf[0]=buf[race*2];
2559 		buf[1]=buf[race*2+1];
2560 	} else if(race<0) {
2561 		int i;
2562 		*len=7;
2563 		for(i=sex;i<14;i+=2) buf[i/2]=buf[i];
2564 	} else {
2565 		*len=1;
2566 		buf[0]=buf[race*2+sex];
2567 	}
2568 }
2569 
set_emote_anim(emote_data * emote,emote_frame * frames,int sex,int race,int held,int idle)2570 void set_emote_anim(emote_data *emote, emote_frame *frames, int sex, int race, int held, int idle){
2571 	int buf[14];
2572 	int len;
2573 	int i,h;
2574 
2575 	h=(held<=0) ? 0:1;
2576 	calc_actor_types(sex,race,buf,&len);
2577 	for(i=0;i<len;i++) {
2578 		if(held<0)
2579 		 	emote->anims[buf[i]][idle][1-h]=frames;
2580 	 	emote->anims[buf[i]][idle][h]=frames;
2581 	}
2582 }
2583 
2584 
flag_emote_frames(emote_data * emote,emote_frame * frame)2585 void flag_emote_frames(emote_data *emote,emote_frame *frame){
2586 	int i,j,k;
2587 	for(i=0;i<EMOTE_ACTOR_TYPES;i++)
2588 		for(j=0;j<4;j++)
2589 			for(k=0;k<2;k++)
2590 				if(emote->anims[i][j][k]==frame)
2591 					emote->anims[i][j][k]=NULL;
2592 }
2593 
free_emote_data(void * data)2594 void free_emote_data(void *data)
2595 {
2596 	emote_data *emote = data;
2597 	emote_frame *head, *frame, *tf;
2598 	int i, j, k;
2599 	if (!emote)
2600 		return;
2601 
2602 	for (i = 0; i < EMOTE_ACTOR_TYPES; i++)
2603 	{
2604 		for (j = 0; j < 4; j++)
2605 		{
2606 			for (k = 0; k < 2; k++)
2607 			{
2608 				head = emote->anims[i][j][k];
2609 				if (!head)
2610 					continue;
2611 
2612 				flag_emote_frames(emote, head);
2613 
2614 				for (frame = head, tf = head->next; tf; frame = tf, tf = tf->next)
2615 					free(frame);
2616 				free(frame);
2617 			}
2618 		}
2619 	}
2620 	free(emote);
2621 }
2622 
new_emote(int id)2623 emote_data *new_emote(int id){
2624 
2625 	emote_data *emote;
2626 
2627 	if(!emotes)
2628 		emotes= create_hash_table(2*EMOTE_CMDS_HASH,hash_fn_int,cmp_fn_int,free_emote_data);
2629 	emote=(emote_data*)calloc(1,sizeof(emote_data));
2630 	init_emote(emote);
2631 	emote->id=id;
2632 	hash_add(emotes,(void *)(uintptr_t)id,(void*)emote);
2633 	return emote;
2634 }
2635 
get_emote_props(const xmlNode * item,int * sex,int * race,int * held)2636 void get_emote_props(const xmlNode *item, int *sex, int *race, int *held)
2637 {
2638 	const char *s_sex,*s_race,*s_held;
2639 	*sex=-1;
2640 	*race=-1;
2641 	*held=-1;
2642 
2643 	s_sex=get_string_property(item,"sex");
2644 	s_race=get_string_property(item,"race");
2645 	s_held=get_string_property(item,"held");
2646 
2647 	if(!strcasecmp(s_sex,"m")) *sex=1;
2648 	if(!strcasecmp(s_sex,"f")) *sex=0;
2649 
2650 	if(!strcasecmp(s_race,"human")) *race=0;
2651 	if(!strcasecmp(s_race,"elf")) *race=1;
2652 	if(!strcasecmp(s_race,"dwarf")) *race=2;
2653 	if(!strcasecmp(s_race,"orchan")) *race=3;
2654 	if(!strcasecmp(s_race,"gnome")) *race=4;
2655 	if(!strcasecmp(s_race,"draegoni")) *race=5;
2656 	if(!strcasecmp(s_race,"monster")) *race=6;
2657 
2658 	if(!strcasecmp(s_held,"true")||!strcasecmp(s_held,"1")) *held=1;
2659 	if(!strcasecmp(s_held,"false")||!strcasecmp(s_held,"0")) *held=0;
2660 }
2661 
2662 
get_emote_frames(const xmlNode * node)2663 emote_frame *get_emote_frames(const xmlNode *node)
2664 {
2665 	const xmlNode *item;
2666 	emote_frame *frames=NULL,*head=NULL;
2667 	char tmp[100];
2668 
2669 	for (item = node->children; item; item = item->next) {
2670 		if (item->type == XML_ELEMENT_NODE) {
2671 			if (xmlStrcasecmp (item->name, (xmlChar*)"anim") == 0) {
2672 				int i,j,k;
2673 				char c;
2674 				i=j=k=0;
2675 				if(!head){
2676 					head=calloc(1,sizeof(emote_frame));
2677 					frames=head;
2678 				} else {
2679 					frames->next=calloc(1,sizeof(emote_frame));
2680 					frames=frames->next;
2681 				}
2682 				get_string_value(tmp, sizeof(tmp), item);
2683 				do {
2684 					j=i;
2685 					while(tmp[i]!='|'&&tmp[i]) i++;
2686 					c=tmp[i];
2687 					tmp[i]=0;
2688 					frames->ids[k++]=atoi(&tmp[j]);
2689 					tmp[i]=c;
2690 					if(c)i++;
2691 				} while(tmp[i]&&k<MAX_EMOTE_FRAME);
2692 				frames->nframes=k;
2693 			} else {
2694 				LOG_ERROR("unknown emote property \"%s\"", item->name);
2695 			}
2696 		}
2697 	}
2698 	return head;
2699 
2700 }
2701 
parse_emote_def(emote_data * emote,const xmlNode * node)2702 int parse_emote_def(emote_data *emote, const xmlNode *node)
2703 {
2704 	const xmlNode *item;
2705 	int ok,s,r,h;
2706 	const char *bare,*pose;
2707 
2708 	if (node == NULL || node->children == NULL) return 0;
2709 
2710 
2711 	bare = get_string_property(node,"barehanded"); //returns "" if not specified
2712 	emote->barehanded = (bare[0]=='L' || bare[0]=='B') ? EMOTE_BARE_L:0;
2713 	emote->barehanded |= (bare[0]=='R' || bare[0]=='B') ? EMOTE_BARE_R:0;
2714 
2715 	pose = get_string_property(node,"pose"); //returns "" if not specified
2716 	emote->pose=EMOTE_STANDING+1;
2717 	if(!strcasecmp(pose,"sitting")) emote->pose = EMOTE_SITTING;
2718 	else if(!strcasecmp(pose,"walking")) emote->pose = EMOTE_WALKING;
2719 	else if(!strcasecmp(pose,"standing")) emote->pose = EMOTE_STANDING;
2720 	else if(!strcasecmp(pose,"running")) emote->pose = EMOTE_RUNNING;
2721 
2722 
2723 	ok = 1;
2724 	for (item = node->children; item; item = item->next) {
2725 		if (item->type == XML_ELEMENT_NODE) {
2726 			if (xmlStrcasecmp (item->name, (xmlChar*)"command") == 0) {
2727 				add_emote_to_dict(item,emote);
2728 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"timeout") == 0) {
2729 				emote->timeout=get_int_value(item);
2730 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"name") == 0) {
2731 				get_string_value(emote->name, sizeof(emote->name), item);
2732 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"desc") == 0) {
2733 				get_string_value(emote->desc, sizeof(emote->desc), item);
2734 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"default") == 0) {
2735 				emote_frame *frames=get_emote_frames(item);
2736 				get_emote_props(item,&s,&r,&h);
2737 				set_emote_anim(emote,frames,s,r,h,EMOTE_SITTING);
2738 				set_emote_anim(emote,frames,s,r,h,EMOTE_WALKING);
2739 				set_emote_anim(emote,frames,s,r,h,EMOTE_STANDING);
2740 				set_emote_anim(emote,frames,s,r,h,EMOTE_RUNNING);
2741 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"sitting") == 0) {
2742 				get_emote_props(item,&s,&r,&h);
2743 				set_emote_anim(emote,get_emote_frames(item),s,r,h,EMOTE_SITTING);
2744 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"walking") == 0) {
2745 				get_emote_props(item,&s,&r,&h);
2746 				set_emote_anim(emote,get_emote_frames(item),s,r,h,EMOTE_WALKING);
2747 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"standing") == 0) {
2748 				get_emote_props(item,&s,&r,&h);
2749 				set_emote_anim(emote,get_emote_frames(item),s,r,h,EMOTE_STANDING);
2750 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"running") == 0) {
2751 				get_emote_props(item,&s,&r,&h);
2752 				set_emote_anim(emote,get_emote_frames(item),s,r,h,EMOTE_RUNNING);
2753 			} else {
2754 				LOG_ERROR("unknown emote property \"%s\"", item->name);
2755 				ok = 0;
2756 			}
2757 		}
2758 	}
2759 
2760 	return ok;
2761 }
2762 
2763 
parse_emotes_defs(const xmlNode * node)2764 int parse_emotes_defs(const xmlNode *node)
2765 {
2766 	const xmlNode *def;
2767 	emote_data *emote = NULL;
2768 	int ok = 1;
2769 
2770 	for (def = node->children; def; def = def->next) {
2771 		if (def->type == XML_ELEMENT_NODE)
2772 			if (xmlStrcasecmp(def->name, (xmlChar*)"emote") == 0) {
2773 				int id = get_int_property(def, "id");
2774 				if (id < 0) {
2775 					LOG_ERROR("Unable to find id property %s\n", def->name);
2776 					ok=0;
2777 				} else {
2778 					emote=new_emote(id);
2779 					ok &= parse_emote_def(emote, def);
2780 				}
2781 			} else if (xmlStrcasecmp(def->name, (xmlChar*)"frames") == 0) {
2782 				int act_type = get_int_property(def, "actor_type");
2783 				if (act_type < 0) {
2784 					ok&=parse_actor_frames(&actors_defs[human_female], def->children, NULL);
2785 					ok&=parse_actor_frames(&actors_defs[human_male], def->children, NULL);
2786 					ok&=parse_actor_frames(&actors_defs[elf_female], def->children, NULL);
2787 					ok&=parse_actor_frames(&actors_defs[elf_male], def->children, NULL);
2788 					ok&=parse_actor_frames(&actors_defs[dwarf_female], def->children, NULL);
2789 					ok&=parse_actor_frames(&actors_defs[dwarf_male], def->children, NULL);
2790 					ok&=parse_actor_frames(&actors_defs[orchan_female], def->children, NULL);
2791 					ok&=parse_actor_frames(&actors_defs[orchan_male], def->children, NULL);
2792 					ok&=parse_actor_frames(&actors_defs[gnome_female], def->children, NULL);
2793 					ok&=parse_actor_frames(&actors_defs[gnome_male], def->children, NULL);
2794 					ok&=parse_actor_frames(&actors_defs[draegoni_female], def->children, NULL);
2795 					ok&=parse_actor_frames(&actors_defs[draegoni_male], def->children, NULL);
2796 				} else ok &= parse_actor_frames(&actors_defs[act_type], def->children, NULL);
2797 			} else{
2798 				LOG_ERROR("parse error: emote or include expected");
2799 				ok = 0;
2800 			}
2801 		else if (def->type == XML_ENTITY_REF_NODE) {
2802 			ok &= parse_emotes_defs(def->children);
2803 		}
2804 	}
2805 
2806 	return ok;
2807 }
2808 
read_emotes_defs(void)2809 int read_emotes_defs(void)
2810 {
2811 	const xmlNode *root;
2812 	xmlDoc *doc;
2813 	const char *fname = "emotes.xml";
2814 	int ok = 1;
2815 
2816 	doc = xmlReadFile(fname, NULL, 0);
2817 	if (doc == NULL) {
2818 		LOG_ERROR("Unable to read emotes definition file %s", fname);
2819 		return 0;
2820 	}
2821 
2822 	root = xmlDocGetRootElement(doc);
2823 	if (root == NULL) {
2824 		LOG_ERROR("Unable to parse emotes definition file %s", fname);
2825 		ok = 0;
2826 	} else if (xmlStrcasecmp(root->name, (xmlChar*)"emotes") != 0) {
2827 		LOG_ERROR("Unknown key \"%s\" (\"emotes\" expected).", root->name);
2828 		ok = 0;
2829 	} else {
2830 		ok = parse_emotes_defs(root);
2831 	}
2832 
2833 	xmlFreeDoc(doc);
2834 	return ok;
2835 }
2836 
2837 
2838 
free_emotes()2839 void free_emotes()
2840 {
2841 	int i;
2842 	for(i=0;i<MAX_ACTOR_DEFS;i++)
2843 		destroy_hash_table(actors_defs[i].emote_frames);
2844 	destroy_hash_table(emote_cmds);
2845 	destroy_hash_table(emotes);
2846 }
2847 
get_default_node(const xmlNode * cfg,const xmlNode * defaults)2848 const xmlNode *get_default_node(const xmlNode *cfg, const xmlNode *defaults)
2849 {
2850 	const xmlNode *item;
2851 	const char *group;
2852 
2853 	// first, check for errors
2854 	if(defaults == NULL || cfg == NULL)
2855 		return NULL;
2856 
2857 	//lets find out what group to look for
2858 	group = get_string_property(cfg, "group");
2859 
2860 	// look for defaul entries with the same name
2861 	for(item=defaults->children; item; item=item->next){
2862 		if(item->type == XML_ELEMENT_NODE) {
2863 			if(xmlStrcasecmp(item->name, cfg->name) == 0){
2864 				const char *item_group;
2865 
2866 				item_group = get_string_property(item, "group");
2867 				// either both have no group, or both groups match
2868 				if(xmlStrcasecmp((xmlChar*)item_group, (xmlChar*)group) == 0){
2869 					// this is the default entry we want then!
2870 					return item;
2871 				}
2872 			}
2873 		}
2874 	}
2875 
2876 	// if we got here, there is no default node that matches
2877 	return NULL;
2878 }
2879 
parse_actor_shirt(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)2880 int parse_actor_shirt(actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
2881 {
2882 	const xmlNode *item;
2883 	int ok, col_idx;
2884 	shirt_part *shirt;
2885 
2886 	if(cfg == NULL || cfg->children == NULL) return 0;
2887 
2888 	col_idx= get_int_property(cfg, "id");
2889 /*	if(col_idx < 0){
2890 		col_idx= get_property(cfg, "color", "shirt color", shirt_color_dict);
2891 	}
2892 */
2893 	if(col_idx < 0 || col_idx >= actor_part_sizes[ACTOR_SHIRT_SIZE]){
2894 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
2895 		return 0;
2896 	}
2897 
2898 	if (act->shirt == NULL) {
2899 		int i;
2900 		act->shirt = (shirt_part*)calloc(actor_part_sizes[ACTOR_SHIRT_SIZE], sizeof(shirt_part));
2901 		for (i = actor_part_sizes[ACTOR_SHIRT_SIZE]; i--;) act->shirt[i].mesh_index= -1;
2902 	}
2903 
2904 	shirt= &(act->shirt[col_idx]);
2905 	ok= 1;
2906 	for(item=cfg->children; item; item=item->next) {
2907 		if(item->type == XML_ELEMENT_NODE) {
2908 			if(xmlStrcasecmp (item->name, (xmlChar*)"arms") == 0) {
2909 				get_string_value(shirt->arms_name, sizeof(shirt->arms_name), item);
2910 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"mesh") == 0) {
2911 				get_string_value(shirt->model_name, sizeof(shirt->model_name), item);
2912 				shirt->mesh_index= cal_load_mesh(act, shirt->model_name, "shirt");
2913 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"torso") == 0) {
2914 				get_string_value(shirt->torso_name, sizeof(shirt->torso_name), item);
2915 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"armsmask") == 0) {
2916 				get_string_value(shirt->arms_mask, sizeof(shirt->arms_mask), item);
2917 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"torsomask") == 0) {
2918 				get_string_value(shirt->torso_mask, sizeof(shirt->torso_mask), item);
2919 			} else {
2920 				LOG_ERROR("unknown shirt property \"%s\"", item->name);
2921 				ok= 0;
2922 			}
2923 		}
2924 	}
2925 
2926 	// check for default entries, if found, use them to fill in missing data
2927 	if(defaults){
2928 		const xmlNode *default_node = get_default_node(cfg, defaults);
2929 
2930 		if(default_node){
2931 			if (*shirt->arms_name=='\0')
2932 				get_item_string_value(shirt->arms_name, sizeof(shirt->arms_name), default_node, (xmlChar*)"arms");
2933 			if (*shirt->model_name=='\0'){
2934 				get_item_string_value(shirt->model_name, sizeof(shirt->model_name), default_node, (xmlChar*)"mesh");
2935 				shirt->mesh_index= cal_load_mesh(act, shirt->model_name, "shirt");
2936 			}
2937 			if (*shirt->torso_name=='\0')
2938 				get_item_string_value(shirt->torso_name, sizeof(shirt->torso_name), default_node, (xmlChar*)"torso");
2939 		}
2940 	}
2941 
2942 	// check the critical information
2943 	actor_check_string(act, "shirt", "arms", shirt->arms_name);
2944 	actor_check_string(act, "shirt", "model", shirt->model_name);
2945 	actor_check_int(act, "shirt", "mesh", shirt->mesh_index);
2946 	actor_check_string(act, "shirt", "torso", shirt->torso_name);
2947 
2948 	return ok;
2949 }
2950 
parse_actor_skin(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)2951 int parse_actor_skin (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
2952 {
2953 	const xmlNode *item;
2954 	int ok, col_idx;
2955 	skin_part *skin;
2956 
2957 	if (cfg == NULL || cfg->children == NULL) return 0;
2958 
2959 	col_idx= get_int_property(cfg, "id");
2960 	if(col_idx < 0){
2961 		col_idx= get_property(cfg, "color", "skin color", skin_color_dict);
2962 	}
2963 
2964 	if(col_idx < 0 || col_idx >= actor_part_sizes[ACTOR_SKIN_SIZE]){
2965 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
2966 		return 0;
2967 	}
2968 
2969 	if (act->skin == NULL) {
2970 		int i;
2971 		act->skin = (skin_part*)calloc(actor_part_sizes[ACTOR_SKIN_SIZE], sizeof(skin_part));
2972 		for (i = actor_part_sizes[ACTOR_SKIN_SIZE]; i--;) act->skin[i].mesh_index= -1;
2973 	}
2974 
2975 	skin = &(act->skin[col_idx]);
2976 	ok = 1;
2977 	for (item = cfg->children; item; item = item->next) {
2978 		if (item->type == XML_ELEMENT_NODE) {
2979 			if (xmlStrcasecmp (item->name, (xmlChar*)"hands") == 0) {
2980 				get_string_value (skin->hands_name, sizeof (skin->hands_name), item);
2981 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"head") == 0) {
2982 				get_string_value (skin->head_name, sizeof (skin->head_name), item);
2983 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"torso") == 0) {
2984 				get_string_value (skin->body_name, sizeof (skin->body_name), item);
2985 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"arms") == 0) {
2986 				get_string_value (skin->arms_name, sizeof (skin->arms_name), item);
2987 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"legs") == 0) {
2988 				get_string_value (skin->legs_name, sizeof (skin->legs_name), item);
2989 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"feet") == 0) {
2990 				get_string_value (skin->feet_name, sizeof (skin->feet_name), item);
2991 			} else {
2992 				LOG_ERROR("unknown skin property \"%s\"", item->name);
2993 				ok = 0;
2994 			}
2995 		}
2996 	}
2997 
2998 	// check for default entries, if found, use them to fill in missing data
2999 	if(defaults){
3000 		const xmlNode *default_node= get_default_node(cfg, defaults);
3001 
3002 		if(default_node){
3003 			if(*skin->hands_name=='\0')
3004 				get_item_string_value(skin->hands_name, sizeof(skin->hands_name), default_node, (xmlChar*)"hands");
3005 			if(*skin->head_name=='\0')
3006 				get_item_string_value(skin->head_name, sizeof(skin->head_name), default_node, (xmlChar*)"head");
3007 		}
3008 	}
3009 
3010 	// check the critical information
3011 	actor_check_string(act, "skin", "hands", skin->hands_name);
3012 	actor_check_string(act, "skin", "head", skin->head_name);
3013 
3014 
3015 	return ok;
3016 }
3017 
parse_actor_legs(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3018 int parse_actor_legs (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3019 {
3020 	const xmlNode *item;
3021 	int ok, col_idx;
3022 	legs_part *legs;
3023 
3024 	if (cfg == NULL || cfg->children == NULL) return 0;
3025 
3026 	col_idx= get_int_property(cfg, "id");
3027 /*	if(col_idx < 0){
3028 		col_idx= get_property(cfg, "color", "legs color", legs_color_dict);
3029 	}
3030 */
3031 	if(col_idx < 0 || col_idx >= actor_part_sizes[ACTOR_LEGS_SIZE]){
3032 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3033 		return 0;
3034 	}
3035 
3036 	if (act->legs == NULL) {
3037 		int i;
3038 		act->legs = (legs_part*)calloc(actor_part_sizes[ACTOR_LEGS_SIZE], sizeof(legs_part));
3039 		for (i = actor_part_sizes[ACTOR_LEGS_SIZE]; i--;) act->legs[i].mesh_index= -1;
3040 	}
3041 
3042 	legs = &(act->legs[col_idx]);
3043 	ok = 1;
3044 	for (item = cfg->children; item; item = item->next) {
3045 		if (item->type == XML_ELEMENT_NODE) {
3046 			if (xmlStrcasecmp (item->name, (xmlChar*)"skin") == 0) {
3047 				get_string_value (legs->legs_name, sizeof (legs->legs_name), item);
3048 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"mesh") == 0) {
3049 				get_string_value (legs->model_name, sizeof (legs->model_name), item);
3050 				legs->mesh_index = cal_load_mesh (act, legs->model_name, "legs");
3051 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"legsmask") == 0) {
3052 				get_string_value (legs->legs_mask, sizeof (legs->legs_mask), item);
3053 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"glow") == 0) {
3054 				int mode = find_description_index (glow_mode_dict, (char*)item->children->content, "glow mode");
3055 				if (mode < 0) mode = GLOW_NONE;
3056 				legs->glow = mode;
3057 			} else {
3058 				LOG_ERROR("unknown legs property \"%s\"", item->name);
3059 				ok = 0;
3060 			}
3061 		}
3062 	}
3063 
3064 	// check for default entries, if found, use them to fill in missing data
3065 	if(defaults){
3066 		const xmlNode *default_node = get_default_node(cfg, defaults);
3067 
3068 		if(default_node){
3069 			if (*legs->legs_name=='\0')
3070 				get_item_string_value(legs->legs_name, sizeof(legs->legs_name), default_node, (xmlChar*)"skin");
3071 			if (*legs->model_name=='\0'){
3072 				get_item_string_value(legs->model_name, sizeof(legs->model_name), default_node, (xmlChar*)"mesh");
3073 				legs->mesh_index= cal_load_mesh(act, legs->model_name, "legs");
3074 			}
3075 		}
3076 	}
3077 
3078 	// check the critical information
3079 	actor_check_string(act, "legs", "skin", legs->legs_name);
3080 	actor_check_string(act, "legs", "model", legs->model_name);
3081 	actor_check_int(act, "legs", "mesh", legs->mesh_index);
3082 
3083 
3084 	return ok;
3085 }
3086 
parse_actor_weapon_detail(actor_types * act,weapon_part * weapon,const xmlNode * cfg,const xmlNode * defaults)3087 int parse_actor_weapon_detail (actor_types *act, weapon_part *weapon, const xmlNode *cfg, const xmlNode *defaults)
3088 {
3089 	const xmlNode *item;
3090 	char str[255];
3091 	char name[256];
3092 	int ok, index;
3093 
3094 	if (cfg == NULL || cfg->children == NULL) return 0;
3095 
3096 	ok = 1;
3097 	for (item = cfg->children; item; item = item->next)
3098 	{
3099 		if (item->type == XML_ELEMENT_NODE)
3100 		{
3101 			safe_strncpy(name, (const char*)item->name, sizeof(name));
3102 			my_tolower(name);
3103 
3104 			if (!strcmp(name, "mesh")) {
3105 				get_string_value (weapon->model_name, sizeof (weapon->model_name), item);
3106 				weapon->mesh_index = cal_load_weapon_mesh (act, weapon->model_name, "weapon");
3107 			} else if (!strcmp(name, "skin")) {
3108 				get_string_value (weapon->skin_name, sizeof (weapon->skin_name), item);
3109 			} else if (!strcmp(name, "skinmask")) {
3110 				get_string_value (weapon->skin_mask, sizeof (weapon->skin_mask), item);
3111 			} else if (!strcmp(name, "glow")) {
3112 				int mode = find_description_index(glow_mode_dict, (char*)item->children->content, "glow mode");
3113 				if (mode < 0) mode = GLOW_NONE;
3114 				weapon->glow = mode;
3115 #ifdef NEW_SOUND
3116 			} else if (!strcmp(name, "snd_attack_up1")) {
3117 				get_string_value (str,sizeof(str),item);
3118 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_1_frame], str, get_string_property(item, "sound_scale"));
3119 			} else if (!strcmp(name, "snd_attack_up2")) {
3120 				get_string_value (str,sizeof(str),item);
3121 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_2_frame], str, get_string_property(item, "sound_scale"));
3122 			} else if (!strcmp(name, "snd_attack_up3")) {
3123 				get_string_value (str,sizeof(str),item);
3124 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_3_frame], str, get_string_property(item, "sound_scale"));
3125 			} else if (!strcmp(name, "snd_attack_up4")) {
3126 				get_string_value (str,sizeof(str),item);
3127 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_4_frame], str, get_string_property(item, "sound_scale"));
3128 			} else if (!strcmp(name, "snd_attack_up5")) {
3129 				get_string_value (str,sizeof(str),item);
3130 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_5_frame], str, get_string_property(item, "sound_scale"));
3131 			} else if (!strcmp(name, "snd_attack_up6")) {
3132 				get_string_value (str,sizeof(str),item);
3133 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_6_frame], str, get_string_property(item, "sound_scale"));
3134 			} else if (!strcmp(name, "snd_attack_up7")) {
3135 				get_string_value (str,sizeof(str),item);
3136 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_7_frame], str, get_string_property(item, "sound_scale"));
3137 			} else if (!strcmp(name, "snd_attack_up8")) {
3138 				get_string_value (str,sizeof(str),item);
3139 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_8_frame], str, get_string_property(item, "sound_scale"));
3140 			} else if (!strcmp(name, "snd_attack_up9")) {
3141 				get_string_value (str,sizeof(str),item);
3142 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_9_frame], str, get_string_property(item, "sound_scale"));
3143 			} else if (!strcmp(name, "snd_attack_up10")) {
3144 				get_string_value (str,sizeof(str),item);
3145 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_up_10_frame], str, get_string_property(item, "sound_scale"));
3146 			} else if (!strcmp(name, "snd_attack_down1")) {
3147 				get_string_value (str,sizeof(str),item);
3148 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_1_frame], str, get_string_property(item, "sound_scale"));
3149 			} else if (!strcmp(name, "snd_attack_down2")) {
3150 				get_string_value (str,sizeof(str),item);
3151 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_2_frame], str, get_string_property(item, "sound_scale"));
3152 			} else if (!strcmp(name, "snd_attack_down3")) {
3153 				get_string_value (str,sizeof(str),item);
3154 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_3_frame], str, get_string_property(item, "sound_scale"));
3155 			} else if (!strcmp(name, "snd_attack_down4")) {
3156 				get_string_value (str,sizeof(str),item);
3157 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_4_frame], str, get_string_property(item, "sound_scale"));
3158 			} else if (!strcmp(name, "snd_attack_down5")) {
3159 				get_string_value (str,sizeof(str),item);
3160 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_5_frame], str, get_string_property(item, "sound_scale"));
3161 			} else if (!strcmp(name, "snd_attack_down6")) {
3162 				get_string_value (str,sizeof(str),item);
3163 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_6_frame], str, get_string_property(item, "sound_scale"));
3164 			} else if (!strcmp(name, "snd_attack_down7")) {
3165 				get_string_value (str,sizeof(str),item);
3166 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_7_frame], str, get_string_property(item, "sound_scale"));
3167 			} else if (!strcmp(name, "snd_attack_down8")) {
3168 				get_string_value (str,sizeof(str),item);
3169 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_8_frame], str, get_string_property(item, "sound_scale"));
3170 			} else if (!strcmp(name, "snd_attack_down9")) {
3171 				get_string_value (str,sizeof(str),item);
3172 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_9_frame], str, get_string_property(item, "sound_scale"));
3173 			} else if (!strcmp(name, "snd_attack_down10")) {
3174 				get_string_value (str,sizeof(str),item);
3175 				cal_set_anim_sound(&weapon->cal_frames[cal_weapon_attack_down_10_frame], str, get_string_property(item, "sound_scale"));
3176 #endif	//NEW_SOUND
3177 			} else {
3178 				index = -1;
3179 				if (!strcmp(name, "cal_attack_up1")) {
3180 					index = cal_weapon_attack_up_1_frame;
3181 				} else if (!strcmp(name, "cal_attack_up2")) {
3182 					index = cal_weapon_attack_up_2_frame;
3183 				} else if (!strcmp(name, "cal_attack_up3")) {
3184 					index = cal_weapon_attack_up_3_frame;
3185 				} else if (!strcmp(name, "cal_attack_up4")) {
3186 					index = cal_weapon_attack_up_4_frame;
3187 				} else if (!strcmp(name, "cal_attack_up5")) {
3188 					index = cal_weapon_attack_up_5_frame;
3189 				} else if (!strcmp(name, "cal_attack_up6")) {
3190 					index = cal_weapon_attack_up_6_frame;
3191 				} else if (!strcmp(name, "cal_attack_up7")) {
3192 					index = cal_weapon_attack_up_7_frame;
3193 				} else if (!strcmp(name, "cal_attack_up8")) {
3194 					index = cal_weapon_attack_up_8_frame;
3195 				} else if (!strcmp(name, "cal_attack_up9")) {
3196 					index = cal_weapon_attack_up_9_frame;
3197 				} else if (!strcmp(name, "cal_attack_up10")) {
3198 					index = cal_weapon_attack_up_10_frame;
3199 				} else if (!strcmp(name, "cal_attack_down1")) {
3200 					index = cal_weapon_attack_down_1_frame;
3201 				} else if (!strcmp(name, "cal_attack_down2")) {
3202 					index = cal_weapon_attack_down_2_frame;
3203 				} else if (!strcmp(name, "cal_attack_down3")) {
3204 					index = cal_weapon_attack_down_3_frame;
3205 				} else if (!strcmp(name, "cal_attack_down4")) {
3206 					index = cal_weapon_attack_down_4_frame;
3207 				} else if (!strcmp(name, "cal_attack_down5")) {
3208 					index = cal_weapon_attack_down_5_frame;
3209 				} else if (!strcmp(name, "cal_attack_down6")) {
3210 					index = cal_weapon_attack_down_6_frame;
3211 				} else if (!strcmp(name, "cal_attack_down7")) {
3212 					index = cal_weapon_attack_down_7_frame;
3213 				} else if (!strcmp(name, "cal_attack_down8")) {
3214 					index = cal_weapon_attack_down_8_frame;
3215 				} else if (!strcmp(name, "cal_attack_down9")) {
3216 					index = cal_weapon_attack_down_9_frame;
3217 				} else if (!strcmp(name, "cal_attack_down10")) {
3218 					index = cal_weapon_attack_down_10_frame;
3219 				}else if (!strcmp(name, "cal_attack_up1_held")) {
3220 					index = cal_weapon_attack_up_1_held_frame;
3221 				} else if (!strcmp(name, "cal_attack_up2_held")) {
3222 					index = cal_weapon_attack_up_2_held_frame;
3223 				} else if (!strcmp(name, "cal_attack_up3_held")) {
3224 					index = cal_weapon_attack_up_3_held_frame;
3225 				} else if (!strcmp(name, "cal_attack_up4_held")) {
3226 					index = cal_weapon_attack_up_4_held_frame;
3227 				} else if (!strcmp(name, "cal_attack_up5_held")) {
3228 					index = cal_weapon_attack_up_5_held_frame;
3229 				} else if (!strcmp(name, "cal_attack_up6_held")) {
3230 					index = cal_weapon_attack_up_6_held_frame;
3231 				} else if (!strcmp(name, "cal_attack_up7_held")) {
3232 					index = cal_weapon_attack_up_7_held_frame;
3233 				} else if (!strcmp(name, "cal_attack_up8_held")) {
3234 					index = cal_weapon_attack_up_8_held_frame;
3235 				} else if (!strcmp(name, "cal_attack_up9_held")) {
3236 					index = cal_weapon_attack_up_9_held_frame;
3237 				} else if (!strcmp(name, "cal_attack_up10_held")) {
3238 					index = cal_weapon_attack_up_10_held_frame;
3239 				} else if (!strcmp(name, "cal_attack_down1_held")) {
3240 					index = cal_weapon_attack_down_1_held_frame;
3241 				} else if (!strcmp(name, "cal_attack_down2_held")) {
3242 					index = cal_weapon_attack_down_2_held_frame;
3243 				} else if (!strcmp(name, "cal_attack_down3_held")) {
3244 					index = cal_weapon_attack_down_3_held_frame;
3245 				} else if (!strcmp(name, "cal_attack_down4_held")) {
3246 					index = cal_weapon_attack_down_4_held_frame;
3247 				} else if (!strcmp(name, "cal_attack_down5_held")) {
3248 					index = cal_weapon_attack_down_5_held_frame;
3249 				} else if (!strcmp(name, "cal_attack_down6_held")) {
3250 					index = cal_weapon_attack_down_6_held_frame;
3251 				} else if (!strcmp(name, "cal_attack_down7_held")) {
3252 					index = cal_weapon_attack_down_7_held_frame;
3253 				} else if (!strcmp(name, "cal_attack_down8_held")) {
3254 					index = cal_weapon_attack_down_8_held_frame;
3255 				} else if (!strcmp(name, "cal_attack_down9_held")) {
3256 					index = cal_weapon_attack_down_9_held_frame;
3257 				} else if (!strcmp(name, "cal_attack_down10_held")) {
3258 					index = cal_weapon_attack_down_10_held_frame;
3259 				} else if (!strcmp(name, "cal_range_fire")) {
3260 					index = cal_weapon_range_fire_frame;
3261 				} else if (!strcmp(name, "cal_range_fire_out")) {
3262 					index = cal_weapon_range_fire_out_frame;
3263 				} else if (!strcmp(name, "cal_range_idle")) {
3264 					index = cal_weapon_range_idle_frame;
3265 				} else if (!strcmp(name, "cal_range_in")) {
3266 					index = cal_weapon_range_in_frame;
3267 				} else if (!strcmp(name, "cal_range_out")) {
3268 					index = cal_weapon_range_out_frame;
3269 				} else if (!strcmp(name, "cal_range_fire_held")) {
3270 					index = cal_weapon_range_fire_held_frame;
3271 				} else if (!strcmp(name, "cal_range_fire_out_held")) {
3272 					index = cal_weapon_range_fire_out_held_frame;
3273 				} else if (!strcmp(name, "cal_range_idle_held")) {
3274 					index = cal_weapon_range_idle_held_frame;
3275 				} else if (!strcmp(name, "cal_range_in_held")) {
3276 					index = cal_weapon_range_in_held_frame;
3277 				} else if (!strcmp(name, "cal_range_out_held")) {
3278 					index = cal_weapon_range_out_held_frame;
3279 				}
3280 				if (index > -1)
3281 				{
3282 					get_string_value (str,sizeof(str),item);
3283 					weapon->cal_frames[index] = cal_load_anim(act, str
3284 #ifdef NEW_SOUND
3285 						, get_string_property(item, "sound")
3286 						, get_string_property(item, "sound_scale")
3287 #endif	//NEW_SOUND
3288 						, get_int_property(item, "duration")
3289 						);
3290 				}
3291 #ifndef NEW_SOUND
3292 				else if (!strcmp(name, "snd_attack_up1") || !strcmp(name, "snd_attack_up2") ||
3293 					!strcmp(name, "snd_attack_up3") || !strcmp(name, "snd_attack_up4") ||
3294 					!strcmp(name, "snd_attack_up5") || !strcmp(name, "snd_attack_up6") ||
3295 					!strcmp(name, "snd_attack_up7") || !strcmp(name, "snd_attack_up8") ||
3296 					!strcmp(name, "snd_attack_up9") || !strcmp(name, "snd_attack_up10") ||
3297 					!strcmp(name, "snd_attack_down1") || !strcmp(name, "snd_attack_down2") ||
3298 					!strcmp(name, "snd_attack_down3") || !strcmp(name, "snd_attack_down4") ||
3299 					!strcmp(name, "snd_attack_down5") || !strcmp(name, "snd_attack_down6") ||
3300 					!strcmp(name, "snd_attack_down7") || !strcmp(name, "snd_attack_down8") ||
3301 					!strcmp(name, "snd_attack_down9") || !strcmp(name, "snd_attack_down10"))
3302 				{ /* ignore */ }
3303 #endif
3304 				else
3305 				{
3306 					LOG_ERROR("unknown weapon property \"%s\"", item->name);
3307 					ok = 0;
3308 				}
3309 			}
3310 		}
3311 		else if (item->type == XML_ENTITY_REF_NODE)
3312 		{
3313 			ok &= parse_actor_weapon_detail(act, weapon, item->children, defaults);
3314 		}
3315 	}
3316 
3317 
3318 	return ok;
3319 }
3320 
parse_actor_weapon(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3321 int parse_actor_weapon(actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3322 {
3323 	int ok, type_idx;
3324 	weapon_part *weapon;
3325 
3326 	if (cfg == NULL || cfg->children == NULL) return 0;
3327 
3328 	type_idx= get_int_property(cfg, "id");
3329 /*	if(type_idx < 0){
3330 		type_idx= get_property(cfg, "type", "weapon type", weapon_type_dict);
3331 	}
3332 */
3333 	if(type_idx < 0 || type_idx >= actor_part_sizes[ACTOR_WEAPON_SIZE]){
3334 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3335 		return 0;
3336 	}
3337 
3338 	if (act->weapon == NULL) {
3339 		int i, j;
3340 		act->weapon = (weapon_part*)calloc(actor_part_sizes[ACTOR_WEAPON_SIZE], sizeof(weapon_part));
3341 		for (i = actor_part_sizes[ACTOR_WEAPON_SIZE]; i--;) {
3342 			act->weapon[i].mesh_index = -1;
3343 			for (j = 0; j < NUM_WEAPON_FRAMES; j++) {
3344 				act->weapon[i].cal_frames[j].anim_index = -1;
3345 #ifdef NEW_SOUND
3346 				act->weapon[i].cal_frames[j].sound = -1;
3347 #endif // NEW_SOUND
3348 			}
3349 		}
3350 	}
3351 
3352 	weapon = &(act->weapon[type_idx]);
3353 	ok= parse_actor_weapon_detail(act, weapon, cfg, defaults);
3354 	weapon->turn_horse=get_int_property(cfg, "turn_horse");
3355 	weapon->unarmed=(get_int_property(cfg, "unarmed")<=0) ? (0):(1);
3356 
3357 	// check for default entries, if found, use them to fill in missing data
3358 	if(defaults){
3359 		const xmlNode *default_node= get_default_node(cfg, defaults);
3360 
3361 		if(default_node){
3362 			if(*weapon->skin_name=='\0')
3363 				get_item_string_value(weapon->skin_name, sizeof(weapon->skin_name), default_node, (xmlChar*)"skin");
3364 			if(type_idx!=GLOVE_FUR && type_idx!=GLOVE_LEATHER){ // these dont have meshes
3365 				if(*weapon->model_name=='\0'){
3366 					get_item_string_value(weapon->model_name, sizeof(weapon->model_name), default_node, (xmlChar*)"mesh");
3367 					weapon->mesh_index= cal_load_weapon_mesh(act, weapon->model_name, "weapon");
3368 				}
3369 			}
3370 			// TODO: combat animations
3371 		}
3372 	}
3373 
3374 	// check the critical information
3375 	if(type_idx!=WEAPON_NONE){   // no weapon doesn't have a skin/model
3376 		actor_check_string(act, "weapon", "skin", weapon->skin_name);
3377 		if(type_idx!=GLOVE_FUR && type_idx!=GLOVE_LEATHER){ // these dont have meshes
3378 			actor_check_string(act, "weapon", "model", weapon->model_name);
3379 			actor_check_int(act, "weapon.mesh", weapon->model_name, weapon->mesh_index);
3380 		}
3381 		// TODO: check combat animations
3382 	}
3383 
3384 
3385 	return ok;
3386 }
3387 
parse_actor_body_part(actor_types * act,body_part * part,const xmlNode * cfg,const char * part_name,const xmlNode * default_node)3388 int parse_actor_body_part (actor_types *act, body_part *part, const xmlNode *cfg, const char *part_name, const xmlNode *default_node)
3389 {
3390 	const xmlNode *item;
3391 	int ok = 1;
3392 
3393 	if(cfg == NULL) return 0;
3394 
3395 	for(item=cfg; item; item=item->next) {
3396 		if(item->type == XML_ELEMENT_NODE) {
3397 			if(xmlStrcasecmp(item->name, (xmlChar*)"mesh") == 0) {
3398 				get_string_value (part->model_name, sizeof (part->model_name), item);
3399 				if(strcmp("shield",part_name)==0)
3400 					part->mesh_index = cal_load_weapon_mesh (act, part->model_name, part_name);
3401 				else
3402 					part->mesh_index = cal_load_mesh (act, part->model_name, part_name);
3403 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"skin") == 0) {
3404 				get_string_value (part->skin_name, sizeof (part->skin_name), item);
3405 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"skinmask") == 0) {
3406 				get_string_value (part->skin_mask, sizeof (part->skin_mask), item);
3407 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"glow") == 0) {
3408 				int mode = find_description_index (glow_mode_dict, (char*)item->children->content, "glow mode");
3409 				if(mode < 0) mode = GLOW_NONE;
3410 				part->glow= mode;
3411 			} else {
3412 				LOG_ERROR("unknown %s property \"%s\"", part_name, item->name);
3413 				ok = 0;
3414 			}
3415 		}
3416 	}
3417 
3418 	// check for default entries, if found, use them to fill in missing data
3419 	if(default_node){
3420 		if(*part->skin_name=='\0')
3421 			if(strcmp(part_name, "head")){ // heads don't have separate skins here
3422 				get_item_string_value(part->skin_name, sizeof(part->skin_name), default_node, (xmlChar*)"skin");
3423 			}
3424 		if(*part->model_name=='\0'){
3425 			get_item_string_value(part->model_name, sizeof(part->model_name), default_node, (xmlChar*)"mesh");
3426 			if(strcmp("shield",part_name)==0)
3427 				part->mesh_index= cal_load_weapon_mesh(act, part->model_name, part_name);
3428 			else
3429 				part->mesh_index= cal_load_mesh(act, part->model_name, part_name);
3430 		}
3431 	}
3432 
3433 	// check the critical information
3434 	if(strcmp(part_name, "head")){ // heads don't have separate skins here
3435 		actor_check_string(act, part_name, "skin", part->skin_name);
3436 	}
3437 	actor_check_string(act, part_name, "model", part->model_name);
3438 	actor_check_int(act, part_name, "mesh", part->mesh_index);
3439 
3440 
3441 	return ok;
3442 }
3443 
parse_actor_helmet(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3444 int parse_actor_helmet (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3445 {
3446 	const xmlNode *default_node= get_default_node(cfg, defaults);
3447 	int type_idx;
3448 	body_part *helmet;
3449 
3450 	if(cfg == NULL || cfg->children == NULL) return 0;
3451 
3452 	type_idx= get_int_property(cfg, "id");
3453 /*	if(type_idx < 0){
3454 		type_idx= get_property(cfg, "type", "helmet type", helmet_type_dict);
3455 	}
3456 */
3457 	if(type_idx < 0 || type_idx >= actor_part_sizes[ACTOR_HELMET_SIZE]){
3458 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3459 		return 0;
3460 	}
3461 
3462 	if (act->helmet == NULL) {
3463 		int i;
3464 		act->helmet = (body_part*)calloc(actor_part_sizes[ACTOR_HELMET_SIZE], sizeof(body_part));
3465 		for (i = actor_part_sizes[ACTOR_HELMET_SIZE]; i--;) act->helmet[i].mesh_index= -1;
3466 	}
3467 
3468 	helmet= &(act->helmet[type_idx]);
3469 
3470 
3471 	return parse_actor_body_part(act,helmet, cfg->children, "helmet", default_node);
3472 }
3473 
parse_actor_neck(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3474 int parse_actor_neck (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3475 {
3476 	const xmlNode *default_node = get_default_node(cfg, defaults);
3477 	int type_idx;
3478 	body_part *neck;
3479 
3480 	if(cfg == NULL || cfg->children == NULL) return 0;
3481 
3482 	type_idx= get_int_property(cfg, "id");
3483 
3484 	if(type_idx < 0 || type_idx >= actor_part_sizes[ACTOR_NECK_SIZE]){
3485 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3486 		return 0;
3487 	}
3488 
3489 	if (act->neck == NULL) {
3490 		int i;
3491 		act->neck = (body_part*)calloc(actor_part_sizes[ACTOR_NECK_SIZE], sizeof(body_part));
3492 		for (i = actor_part_sizes[ACTOR_NECK_SIZE]; i--;) act->neck[i].mesh_index= -1;
3493 	}
3494 
3495 	neck= &(act->neck[type_idx]);
3496 
3497 	return parse_actor_body_part(act,neck, cfg->children, "neck", default_node);
3498 }
3499 
3500 #ifdef NEW_SOUND
parse_actor_sounds(actor_types * act,const xmlNode * cfg)3501 int parse_actor_sounds(actor_types *act, const xmlNode *cfg)
3502 {
3503 	const xmlNode *item;
3504 	char str[255];
3505 	int ok;
3506 	int i;
3507 
3508 	if (cfg == NULL) return 0;
3509 	if (!have_sound_config) return 0;
3510 
3511 	ok = 1;
3512 	for (item = cfg; item; item = item->next) {
3513 		if (item->type == XML_ELEMENT_NODE) {
3514 			get_string_value (str,sizeof(str),item);
3515 			if (xmlStrcasecmp (item->name, (xmlChar*)"walk") == 0) {
3516 				cal_set_anim_sound(&act->cal_frames[cal_actor_walk_frame], str, get_string_property(item, "sound_scale"));
3517 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"run") == 0) {
3518 				cal_set_anim_sound(&act->cal_frames[cal_actor_run_frame], str, get_string_property(item, "sound_scale"));
3519 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"die1") == 0) {
3520 				cal_set_anim_sound(&act->cal_frames[cal_actor_die1_frame], str, get_string_property(item, "sound_scale"));
3521 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"die2") == 0) {
3522 				cal_set_anim_sound(&act->cal_frames[cal_actor_die2_frame], str, get_string_property(item, "sound_scale"));
3523 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"pain1") == 0) {
3524 				cal_set_anim_sound(&act->cal_frames[cal_actor_pain1_frame], str, get_string_property(item, "sound_scale"));
3525 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"pain2") == 0) {
3526 				cal_set_anim_sound(&act->cal_frames[cal_actor_pain2_frame], str, get_string_property(item, "sound_scale"));
3527 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"pick") == 0) {
3528 				cal_set_anim_sound(&act->cal_frames[cal_actor_pick_frame], str, get_string_property(item, "sound_scale"));
3529 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"drop") == 0) {
3530 				cal_set_anim_sound(&act->cal_frames[cal_actor_drop_frame], str, get_string_property(item, "sound_scale"));
3531 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"harvest") == 0) {
3532 				cal_set_anim_sound(&act->cal_frames[cal_actor_harvest_frame], str, get_string_property(item, "sound_scale"));
3533 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"attack_cast") == 0) {
3534 				cal_set_anim_sound(&act->cal_frames[cal_actor_attack_cast_frame], str, get_string_property(item, "sound_scale"));
3535 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"attack_ranged") == 0) {
3536 				cal_set_anim_sound(&act->cal_frames[cal_actor_attack_ranged_frame], str, get_string_property(item, "sound_scale"));
3537 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"sit_down") == 0) {
3538 				cal_set_anim_sound(&act->cal_frames[cal_actor_sit_down_frame], str, get_string_property(item, "sound_scale"));
3539 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"stand_up") == 0) {
3540 				cal_set_anim_sound(&act->cal_frames[cal_actor_stand_up_frame], str, get_string_property(item, "sound_scale"));
3541 			// These sounds are only found in the <sounds> block as they aren't tied to an animation
3542 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"battlecry") == 0) {
3543 				i = get_index_for_sound_type_name(str);
3544 				if (i == -1)
3545 					LOG_ERROR("Unknown battlecry sound (%s) in actor def: %s", str, act->actor_name);
3546 				else
3547 				{
3548 					act->battlecry.sound = i;
3549 					safe_strncpy(str, get_string_property(item, "sound_scale"), sizeof(str));
3550 					if (strcasecmp(str, ""))
3551 						act->battlecry.scale = atof(str);
3552 					else
3553 						act->battlecry.scale = 1.0f;
3554 				}
3555 			} else {
3556 				LOG_ERROR("Unknown sound \"%s\"", item->name);
3557 				ok = 0;
3558 			}
3559 		}
3560 	}
3561 
3562 	return ok;
3563 }
3564 #endif	//NEW_SOUND
3565 
parse_actor_cape(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3566 int parse_actor_cape (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3567 {
3568 	const xmlNode *default_node = get_default_node(cfg, defaults);
3569 	int type_idx;
3570 	body_part *cape;
3571 
3572 	if(cfg == NULL || cfg->children == NULL) return 0;
3573 
3574 	type_idx= get_int_property(cfg, "id");
3575 /*	if(type_idx < 0){
3576 		type_idx= get_property(cfg, "color", "cape color", cape_color_dict);
3577 	}
3578 */
3579 	if(type_idx < 0 || type_idx >= actor_part_sizes[ACTOR_CAPE_SIZE]){
3580 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3581 		return 0;
3582 	}
3583 
3584 	if (act->cape == NULL) {
3585 		int i;
3586 		act->cape = (body_part*)calloc(actor_part_sizes[ACTOR_CAPE_SIZE], sizeof(body_part));
3587 		for (i = actor_part_sizes[ACTOR_CAPE_SIZE]; i--;) act->cape[i].mesh_index= -1;
3588 	}
3589 
3590 	cape= &(act->cape[type_idx]);
3591 
3592 
3593 	return parse_actor_body_part(act,cape, cfg->children, "cape", default_node);
3594 }
3595 
parse_actor_head(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3596 int parse_actor_head (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3597 {
3598 	const xmlNode *default_node= get_default_node(cfg, defaults);
3599 	int type_idx;
3600 	body_part *head;
3601 
3602 	if(cfg == NULL || cfg->children == NULL) return 0;
3603 
3604 	type_idx= get_int_property(cfg, "id");
3605 	if(type_idx < 0){
3606 		type_idx= get_property(cfg, "number", "head number", head_number_dict);
3607 	}
3608 
3609 	if(type_idx < 0 || type_idx >= actor_part_sizes[ACTOR_HEAD_SIZE]){
3610 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3611 		return 0;
3612 	}
3613 
3614 	if (act->head == NULL) {
3615 		int i;
3616 		act->head = (body_part*)calloc(actor_part_sizes[ACTOR_HEAD_SIZE], sizeof(body_part));
3617 		for (i = actor_part_sizes[ACTOR_HEAD_SIZE]; i--;) act->head[i].mesh_index= -1;
3618 	}
3619 
3620 	head= &(act->head[type_idx]);
3621 
3622 
3623 
3624 	return parse_actor_body_part(act, head, cfg->children, "head", default_node);
3625 }
3626 
parse_actor_shield_part(actor_types * act,shield_part * part,const xmlNode * cfg,const xmlNode * default_node)3627 int parse_actor_shield_part (actor_types *act, shield_part *part, const xmlNode *cfg, const xmlNode *default_node)
3628 {
3629 	const xmlNode *item;
3630 	int ok = 1;
3631 
3632 	if(cfg == NULL) return 0;
3633 
3634 	for(item=cfg; item; item=item->next) {
3635 		if(item->type == XML_ELEMENT_NODE) {
3636 			if(xmlStrcasecmp(item->name, (xmlChar*)"mesh") == 0) {
3637 				get_string_value (part->model_name, sizeof (part->model_name), item);
3638 				part->mesh_index = cal_load_weapon_mesh (act, part->model_name, "shield");
3639 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"skin") == 0) {
3640 				get_string_value (part->skin_name, sizeof (part->skin_name), item);
3641 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"skinmask") == 0) {
3642 				get_string_value (part->skin_mask, sizeof (part->skin_mask), item);
3643 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"glow") == 0) {
3644 				int mode = find_description_index (glow_mode_dict, (char*)item->children->content, "glow mode");
3645 				if(mode < 0) mode = GLOW_NONE;
3646 				part->glow= mode;
3647 			} else if(xmlStrcasecmp(item->name, (xmlChar*)"missile") == 0) {
3648 				part->missile_type = get_int_value(item);
3649 			} else {
3650 				LOG_ERROR("unknown shield property \"%s\"", item->name);
3651 				ok = 0;
3652 			}
3653 		}
3654 	}
3655 
3656 	// check for default entries, if found, use them to fill in missing data
3657 	if(default_node){
3658 		if(*part->model_name=='\0'){
3659 			get_item_string_value(part->model_name, sizeof(part->model_name), default_node, (xmlChar*)"mesh");
3660 			part->mesh_index= cal_load_weapon_mesh(act, part->model_name, "shield");
3661 		}
3662 	}
3663 
3664 	// check the critical information
3665 	actor_check_string(act, "shield", "model", part->model_name);
3666 	actor_check_int(act, "shield", "mesh", part->mesh_index);
3667 
3668 
3669 	return ok;
3670 }
3671 
parse_actor_shield(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3672 int parse_actor_shield (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3673 {
3674 	const xmlNode *default_node = get_default_node(cfg, defaults);
3675 	int type_idx;
3676 	shield_part *shield;
3677 
3678 	if(cfg == NULL || cfg->children == NULL) return 0;
3679 
3680 	type_idx= get_int_property(cfg, "id");
3681 /*	if(type_idx < 0){
3682 		type_idx= get_property(cfg, "type", "shield type", shield_type_dict);
3683 	}
3684 */
3685 	if(type_idx < 0 || type_idx >= actor_part_sizes[ACTOR_SHIELD_SIZE]){
3686 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3687 		return 0;
3688 	}
3689 
3690 	if (act->shield == NULL) {
3691 		int i;
3692 		act->shield = (shield_part*)calloc(actor_part_sizes[ACTOR_SHIELD_SIZE], sizeof(shield_part));
3693 		for (i = actor_part_sizes[ACTOR_SHIELD_SIZE]; i--;) {
3694 			act->shield[i].mesh_index = -1;
3695 			act->shield[i].missile_type = -1;
3696 		}
3697 	}
3698 
3699 	shield= &(act->shield[type_idx]);
3700 
3701 
3702 	return parse_actor_shield_part(act, shield, cfg->children, default_node);
3703 }
3704 
parse_actor_hair(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3705 int parse_actor_hair (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3706 {
3707 	int col_idx;
3708 	size_t len;
3709 	char *buf;
3710 
3711 	if(cfg == NULL || cfg->children == NULL) return 0;
3712 
3713 	col_idx= get_int_property(cfg, "id");
3714 /*	if(col_idx < 0){
3715 		col_idx= get_property(cfg, "color", "hair color", hair_color_dict);
3716 	}
3717 */
3718 	if(col_idx < 0 || col_idx >= actor_part_sizes[ACTOR_HAIR_SIZE]){
3719 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3720 		return 0;
3721 	}
3722 
3723 	if (act->hair == NULL) {
3724 		int i;
3725 		act->hair = (hair_part*)calloc(actor_part_sizes[ACTOR_HAIR_SIZE], sizeof(hair_part));
3726 		for (i = actor_part_sizes[ACTOR_HAIR_SIZE]; i--;) act->hair[i].mesh_index= -1;
3727 	}
3728 
3729 	buf= act->hair[col_idx].hair_name;
3730 	len= sizeof (act->hair[col_idx].hair_name);
3731 	get_string_value(buf, len, cfg);
3732 
3733 
3734 	return 1;
3735 }
3736 
parse_actor_eyes(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3737 int parse_actor_eyes (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3738 {
3739 	int col_idx;
3740 	size_t len;
3741 	char *buf;
3742 
3743 	if(cfg == NULL || cfg->children == NULL) return 0;
3744 
3745 	col_idx= get_int_property(cfg, "id");
3746 /*	if(col_idx < 0){
3747 		col_idx= get_property(cfg, "color", "eyes color", eyes_color_dict);
3748 	}
3749 */
3750 	if(col_idx < 0 || col_idx >= actor_part_sizes[ACTOR_EYES_SIZE]){
3751 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
3752 		return 0;
3753 	}
3754 
3755 	if (act->eyes == NULL) {
3756 		int i;
3757 		act->eyes = (eyes_part*)calloc(actor_part_sizes[ACTOR_EYES_SIZE], sizeof(eyes_part));
3758 		for (i = actor_part_sizes[ACTOR_EYES_SIZE]; i--;) act->eyes[i].mesh_index= -1;
3759 	}
3760 
3761 	buf= act->eyes[col_idx].eyes_name;
3762 	len= sizeof (act->eyes[col_idx].eyes_name);
3763 	get_string_value(buf, len, cfg);
3764 
3765 
3766 	return 1;
3767 }
3768 
cal_get_idle_group(actor_types * act,char * name)3769 int cal_get_idle_group(actor_types *act,char *name)
3770 {
3771 	int i;
3772 	int res=-1;
3773 
3774 	for (i=0;i<act->group_count;++i) {
3775 		if (strcmp(name,act->idle_group[i].name)==0) res=i;
3776 	}
3777 
3778 	if (res>=0) return res;//Found it, return
3779 
3780 	//Create a new named group
3781 	res=act->group_count;
3782 	safe_strncpy(act->idle_group[res].name, name, sizeof(act->idle_group[res].name));
3783 	++act->group_count;
3784 
3785 	return res;
3786 }
3787 
cal_load_idle(actor_types * act,char * str)3788 struct cal_anim cal_load_idle(actor_types *act, char *str)
3789 {
3790 	struct cal_anim res={-1,0,0,0.0f
3791 #ifdef NEW_SOUND
3792 	,-1
3793 	,0.0f
3794 #endif  //NEW_SOUND
3795 	};
3796 	struct CalCoreAnimation *coreanim;
3797 
3798 	res.anim_index=CalCoreModel_ELLoadCoreAnimation(act->coremodel,str,act->scale);
3799 	if(res.anim_index == -1) {
3800 		LOG_ERROR("Cal3d error: %s: %s\n", str, CalError_GetLastErrorDescription());
3801 		return res;
3802 	}
3803 	coreanim=CalCoreModel_GetCoreAnimation(act->coremodel,res.anim_index);
3804 
3805 	if (coreanim) {
3806 		res.duration=CalCoreAnimation_GetDuration(coreanim);
3807 	} else {
3808 		LOG_ERROR("No Anim: %s\n",str);
3809 	}
3810 
3811 	return res;
3812 }
3813 
cal_group_addanim(actor_types * act,int gindex,char * fanim)3814 void cal_group_addanim(actor_types *act,int gindex, char *fanim)
3815 {
3816 	int i;
3817 
3818 	i=act->idle_group[gindex].count;
3819 	act->idle_group[gindex].anim[i]=cal_load_idle(act,fanim);
3820 	//LOG_TO_CONSOLE(c_green2,fanim);
3821 	++act->idle_group[gindex].count;
3822 }
3823 
parse_idle_group(actor_types * act,const char * str)3824 void parse_idle_group (actor_types *act, const char *str)
3825 {
3826 	char gname[255]={0};
3827 	char fname[255]={0};
3828 	//char temp[255];
3829 	int gindex;
3830 
3831 	if (sscanf (str, "%254s %254s", gname, fname) != 2) return;
3832 
3833 	gindex=cal_get_idle_group(act,gname);
3834 	cal_group_addanim(act,gindex,fname);
3835 	//safe_snprintf(temp, sizeof(temp), "%d",gindex);
3836 	//LOG_TO_CONSOLE(c_green2,gname);
3837 	//LOG_TO_CONSOLE(c_green2,fname);
3838 	//LOG_TO_CONSOLE(c_green2,temp);
3839 }
3840 
parse_actor_frames(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)3841 int parse_actor_frames (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
3842 {
3843 	const xmlNode *item;
3844 	char str[255];
3845 	int ok = 1;
3846 
3847 	if (cfg == NULL) return 0;
3848 
3849 	for (item = cfg; item; item = item->next) {
3850 		if (item->type == XML_ELEMENT_NODE) {
3851 			int index = -1;
3852 			if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_IDLE_GROUP") == 0) {
3853 				get_string_value (str,sizeof(str),item);
3854      				//act->cal_walk_frame=cal_load_anim(act,str);
3855 				//LOG_TO_CONSOLE(c_green2,str);
3856 				parse_idle_group(act,str);
3857 				//Not functional!
3858 				index = -2;
3859 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_walk") == 0) {
3860 				index = cal_actor_walk_frame;
3861 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_run") == 0) {
3862 				index = cal_actor_run_frame;
3863 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_turn_left") == 0) {
3864 				index = cal_actor_turn_left_frame;
3865 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_turn_right") == 0) {
3866 				index = cal_actor_turn_right_frame;
3867 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_die1") == 0) {
3868 				index = cal_actor_die1_frame;
3869 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_die2") == 0) {
3870 				index = cal_actor_die2_frame;
3871 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_pain1") == 0) {
3872 				index = cal_actor_pain1_frame;
3873 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_pain2") == 0) {
3874 				index = cal_actor_pain2_frame;
3875 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_pick") == 0) {
3876 				index = cal_actor_pick_frame;
3877 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_drop") == 0) {
3878 				index = cal_actor_drop_frame;
3879 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_idle") == 0) {
3880 				index = cal_actor_idle1_frame;
3881 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_idle2") == 0) {
3882 				index = cal_actor_idle2_frame;
3883 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_idle_sit") == 0) {
3884 				index = cal_actor_idle_sit_frame;
3885  			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_harvest") == 0) {
3886 				index = cal_actor_harvest_frame;
3887 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_cast") == 0) {
3888 				index = cal_actor_attack_cast_frame;
3889 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_sit_down") == 0) {
3890 				index = cal_actor_sit_down_frame;
3891 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_stand_up") == 0) {
3892 				index = cal_actor_stand_up_frame;
3893 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_in_combat") == 0) {
3894 				index = cal_actor_in_combat_frame;
3895 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_out_combat") == 0) {
3896 				index = cal_actor_out_combat_frame;
3897 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_combat_idle") == 0) {
3898 				index = cal_actor_combat_idle_frame;
3899 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_1") == 0) {
3900 				index = cal_actor_attack_up_1_frame;
3901 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_2") == 0) {
3902 				index = cal_actor_attack_up_2_frame;
3903 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_3") == 0) {
3904 				index = cal_actor_attack_up_3_frame;
3905 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_4") == 0) {
3906 				index = cal_actor_attack_up_4_frame;
3907 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_5") == 0) {
3908 				index = cal_actor_attack_up_5_frame;
3909 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_6") == 0) {
3910 				index = cal_actor_attack_up_6_frame;
3911 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_7") == 0) {
3912 				index = cal_actor_attack_up_7_frame;
3913 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_8") == 0) {
3914 				index = cal_actor_attack_up_8_frame;
3915 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_9") == 0) {
3916 				index = cal_actor_attack_up_9_frame;
3917 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_10") == 0) {
3918 				index = cal_actor_attack_up_10_frame;
3919 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_1") == 0) {
3920 				index = cal_actor_attack_down_1_frame;
3921 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_2") == 0) {
3922 				index = cal_actor_attack_down_2_frame;
3923 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_3") == 0) {
3924 				index = cal_actor_attack_down_3_frame;
3925 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_4") == 0) {
3926 				index = cal_actor_attack_down_4_frame;
3927 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_5") == 0) {
3928 				index = cal_actor_attack_down_5_frame;
3929 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_6") == 0) {
3930 				index = cal_actor_attack_down_6_frame;
3931 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_7") == 0) {
3932 				index = cal_actor_attack_down_7_frame;
3933 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_8") == 0) {
3934 				index = cal_actor_attack_down_8_frame;
3935 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_9") == 0) {
3936 				index = cal_actor_attack_down_9_frame;
3937 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_10") == 0) {
3938 				index = cal_actor_attack_down_10_frame;
3939 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_in_combat_held") == 0) {
3940 				index = cal_actor_in_combat_held_frame;
3941 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_out_combat_held") == 0) {
3942 				index = cal_actor_out_combat_held_frame;
3943 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_combat_idle_held") == 0) {
3944 				index = cal_actor_combat_idle_held_frame;
3945 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_in_combat_held_unarmed") == 0) {
3946 				index = cal_actor_in_combat_held_unarmed_frame;
3947 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_out_combat_held_unarmed") == 0) {
3948 				index = cal_actor_out_combat_held_unarmed_frame;
3949 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_combat_idle_held_unarmed") == 0) {
3950 				index = cal_actor_combat_idle_held_unarmed_frame;
3951 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_1_held") == 0) {
3952 				index = cal_actor_attack_up_1_held_frame;
3953 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_2_held") == 0) {
3954 				index = cal_actor_attack_up_2_held_frame;
3955 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_3_held") == 0) {
3956 				index = cal_actor_attack_up_3_held_frame;
3957 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_4_held") == 0) {
3958 				index = cal_actor_attack_up_4_held_frame;
3959 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_5_held") == 0) {
3960 				index = cal_actor_attack_up_5_held_frame;
3961 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_6_held") == 0) {
3962 				index = cal_actor_attack_up_6_held_frame;
3963 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_7_held") == 0) {
3964 				index = cal_actor_attack_up_7_held_frame;
3965 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_8_held") == 0) {
3966 				index = cal_actor_attack_up_8_held_frame;
3967 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_9_held") == 0) {
3968 				index = cal_actor_attack_up_9_held_frame;
3969 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_up_10_held") == 0) {
3970 				index = cal_actor_attack_up_10_held_frame;
3971 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_1_held") == 0) {
3972 				index = cal_actor_attack_down_1_held_frame;
3973 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_2_held") == 0) {
3974 				index = cal_actor_attack_down_2_held_frame;
3975 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_3_held") == 0) {
3976 				index = cal_actor_attack_down_3_held_frame;
3977 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_4_held") == 0) {
3978 				index = cal_actor_attack_down_4_held_frame;
3979 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_5_held") == 0) {
3980 				index = cal_actor_attack_down_5_held_frame;
3981 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_6_held") == 0) {
3982 				index = cal_actor_attack_down_6_held_frame;
3983 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_7_held") == 0) {
3984 				index = cal_actor_attack_down_7_held_frame;
3985 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_8_held") == 0) {
3986 				index = cal_actor_attack_down_8_held_frame;
3987 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_9_held") == 0) {
3988 				index = cal_actor_attack_down_9_held_frame;
3989 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_attack_down_10_held") == 0) {
3990 				index = cal_actor_attack_down_10_held_frame;
3991 			} else {
3992 				int j;
3993 				char *etag="CAL_emote";
3994 				struct cal_anim *anim;
3995 				if(!strncasecmp(etag,(const char*) item->name,9)) {
3996 					//load emote frame
3997 					j=get_int_property(item,"index");
3998 					get_string_value(str, sizeof(str), item);
3999 					if(!act->emote_frames)
4000 						act->emote_frames=create_hash_table(EMOTES_FRAMES,hash_fn_int,cmp_fn_int,free);
4001 					anim=calloc(1,sizeof(struct cal_anim));
4002 		     			*anim = cal_load_anim(act, str
4003 #ifdef NEW_SOUND
4004 					, get_string_property(item, "sound")
4005 					, get_string_property(item, "sound_scale")
4006 #endif	//NEW_SOUND
4007 					, get_int_property(item, "duration")
4008 					);
4009 					hash_add(act->emote_frames, (void *)(uintptr_t)j, (void*)anim);
4010 					continue;
4011 				}
4012 			}
4013 
4014 			if (index >= 0)
4015 			{
4016 				get_string_value(str, sizeof(str), item);
4017      			act->cal_frames[index] = cal_load_anim(act, str
4018 #ifdef NEW_SOUND
4019 					, get_string_property(item, "sound")
4020 					, get_string_property(item, "sound_scale")
4021 #endif	//NEW_SOUND
4022 					, get_int_property(item, "duration")
4023 					);
4024 			}
4025 			else if (index != -2)
4026 			{
4027 				LOG_ERROR("unknown frame property \"%s\"", item->name);
4028 				ok = 0;
4029 			}
4030 		}
4031 	}
4032 
4033 	return ok;
4034 }
4035 
parse_actor_attachment(actor_types * act,const xmlNode * cfg,int actor_type)4036 int parse_actor_attachment (actor_types *act, const xmlNode *cfg, int actor_type)
4037 {
4038 	const xmlNode *item;
4039 	int ok = 1;
4040 	attached_actors_types *att = &attached_actors_defs[act->actor_type];
4041 	actor_types *held_act = NULL;
4042 	char str[256];
4043 	struct CalCoreSkeleton *skel;
4044 
4045 	if (cfg == NULL || cfg->children == NULL) return 0;
4046 
4047 	for (item = cfg->children; item; item = item->next) {
4048 		if (item->type == XML_ELEMENT_NODE) {
4049 			if (xmlStrcasecmp (item->name, (xmlChar*)"holder") == 0) {
4050 				att->actor_type[actor_type].is_holder = get_bool_value(item);
4051 				if (att->actor_type[actor_type].is_holder)
4052 					held_act = &actors_defs[actor_type];
4053 				else
4054 					held_act = act;
4055 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"parent_bone") == 0) {
4056 				get_string_value (str, sizeof (str), item);
4057 				skel = CalCoreModel_GetCoreSkeleton(actors_defs[actor_type].coremodel);
4058 				if (skel) {
4059 					att->actor_type[actor_type].parent_bone_id = find_core_bone_id(skel, str);
4060 					if (att->actor_type[actor_type].parent_bone_id < 0) {
4061 						LOG_ERROR("bone %s was not found in skeleton of actor type %d", str, actor_type);
4062 						ok = 0;
4063 					}
4064 				}
4065 				else {
4066 					LOG_ERROR("the skeleton for actor type %d doesn't exist!", actor_type);
4067 					ok = 0;
4068 				}
4069 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"local_bone") == 0) {
4070 				get_string_value (str, sizeof (str), item);
4071 				skel = CalCoreModel_GetCoreSkeleton(act->coremodel);
4072 				if (skel) {
4073 					att->actor_type[actor_type].local_bone_id = find_core_bone_id(skel, str);
4074 					if (att->actor_type[actor_type].local_bone_id < 0) {
4075 						LOG_ERROR("bone %s was not found in skeleton of actor type %d", str, act->actor_type);
4076 						ok = 0;
4077 					}
4078 				}
4079 				else {
4080 					LOG_ERROR("the skeleton for actor type %d doesn't exist!", act->actor_type);
4081 					ok = 0;
4082 				}
4083 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"held_shift") == 0) {
4084 				xmlAttr *attr;
4085 				for (attr = item->properties; attr; attr = attr->next)
4086 					if (attr->type == XML_ATTRIBUTE_NODE)
4087 					{
4088 						if (xmlStrcasecmp (attr->name, (xmlChar*)"x") == 0)
4089 							att->actor_type[actor_type].shift[0] = atof((char*)attr->children->content);
4090 						else if (xmlStrcasecmp (attr->name, (xmlChar*)"y") == 0)
4091 							att->actor_type[actor_type].shift[1] = atof((char*)attr->children->content);
4092 						else if (xmlStrcasecmp (attr->name, (xmlChar*)"z") == 0)
4093 							att->actor_type[actor_type].shift[2] = atof((char*)attr->children->content);
4094 						else {
4095 							LOG_ERROR("unknown attachment shift attribute \"%s\"", attr->name);
4096 							ok = 0;
4097 						}
4098 					}
4099 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_held_walk") == 0) {
4100 				get_string_value (str, sizeof(str), item);
4101      			att->actor_type[actor_type].cal_frames[cal_attached_walk_frame] = cal_load_anim(held_act, str
4102 #ifdef NEW_SOUND
4103 					, get_string_property(item, "sound")
4104 					, get_string_property(item, "sound_scale")
4105 #endif	//NEW_SOUND
4106 					, get_int_property(item, "duration")
4107 					);
4108 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_held_run") == 0) {
4109 				get_string_value (str, sizeof(str), item);
4110      			att->actor_type[actor_type].cal_frames[cal_attached_run_frame] = cal_load_anim(held_act, str
4111 #ifdef NEW_SOUND
4112 					, get_string_property(item, "sound")
4113 					, get_string_property(item, "sound_scale")
4114 #endif	//NEW_SOUND
4115 					, get_int_property(item, "duration")
4116 					);
4117 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_held_idle") == 0) {
4118 				get_string_value (str,sizeof(str),item);
4119      			att->actor_type[actor_type].cal_frames[cal_attached_idle_frame] = cal_load_anim(held_act, str
4120 #ifdef NEW_SOUND
4121 					, get_string_property(item, "sound")
4122 					, get_string_property(item, "sound_scale")
4123 #endif	//NEW_SOUND
4124 					, get_int_property(item, "duration")
4125 					);
4126 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_held_pain") == 0) {
4127 				get_string_value (str,sizeof(str),item);
4128      			att->actor_type[actor_type].cal_frames[cal_attached_pain_frame] = cal_load_anim(held_act, str
4129 #ifdef NEW_SOUND
4130 					, get_string_property(item, "sound")
4131 					, get_string_property(item, "sound_scale")
4132 #endif	//NEW_SOUND
4133 					, get_int_property(item, "duration")
4134 					);
4135 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"CAL_held_armed_pain") == 0) {
4136 				get_string_value (str,sizeof(str),item);
4137      			att->actor_type[actor_type].cal_frames[cal_attached_pain_armed_frame] = cal_load_anim(held_act, str
4138 #ifdef NEW_SOUND
4139 					, get_string_property(item, "sound")
4140 					, get_string_property(item, "sound_scale")
4141 #endif	//NEW_SOUND
4142 					, get_int_property(item, "duration")
4143 					);
4144 			} else {
4145 				LOG_ERROR("unknown attachment property \"%s\"", item->name);
4146 				ok = 0;
4147 			}
4148 		} else if (item->type == XML_ENTITY_REF_NODE) {
4149 			ok &= parse_actor_attachment(act, item->children, actor_type);
4150 		}
4151 	}
4152 
4153 	return ok;
4154 }
4155 
parse_actor_boots(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)4156 int parse_actor_boots (actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
4157 {
4158 	const xmlNode *item;
4159 	int ok, col_idx;
4160 	boots_part *boots;
4161 
4162 	if (cfg == NULL || cfg->children == NULL) return 0;
4163 
4164 	col_idx= get_int_property(cfg, "id");
4165 /*	if(col_idx < 0){
4166 		col_idx = get_property (cfg, "color", "boots color", boots_color_dict);
4167 	}
4168 */
4169 	if(col_idx < 0 || col_idx >= actor_part_sizes[ACTOR_BOOTS_SIZE]){
4170 		LOG_ERROR("Unable to find id/property node %s\n", cfg->name);
4171 		return 0;
4172 	}
4173 
4174 	if (act->boots == NULL) {
4175 		int i;
4176 		act->boots = (boots_part*)calloc(actor_part_sizes[ACTOR_BOOTS_SIZE], sizeof(boots_part));
4177 		for (i = actor_part_sizes[ACTOR_BOOTS_SIZE]; i--;) act->boots[i].mesh_index= -1;
4178 	}
4179 
4180 	boots = &(act->boots[col_idx]);
4181 	ok = 1;
4182 	for (item = cfg->children; item; item = item->next) {
4183 		if (item->type == XML_ELEMENT_NODE) {
4184 			if (xmlStrcasecmp (item->name, (xmlChar*)"skin") == 0) {
4185 				get_string_value (boots->boots_name, sizeof (boots->boots_name), item);
4186 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"mesh") == 0) {
4187 				get_string_value (boots->model_name, sizeof (boots->model_name), item);
4188 				boots->mesh_index = cal_load_mesh (act, boots->model_name, "boots");
4189 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"bootsmask") == 0) {
4190 				get_string_value (boots->boots_mask, sizeof (boots->boots_mask), item);
4191 			} else if (xmlStrcasecmp (item->name, (xmlChar*)"glow") == 0) {
4192 				int mode = find_description_index (glow_mode_dict, (char*)item->children->content, "glow mode");
4193 				if (mode < 0) mode = GLOW_NONE;
4194 				boots->glow = mode;
4195 			} else {
4196 				LOG_ERROR("unknown legs property \"%s\"", item->name);
4197 				ok = 0;
4198 			}
4199 		}
4200 	}
4201 
4202 	// check for default entries, if found, use them to fill in missing data
4203 	if(defaults){
4204 		const xmlNode *default_node = get_default_node(cfg, defaults);
4205 
4206 		if(default_node){
4207 			if (*boots->boots_name=='\0')
4208 				get_item_string_value(boots->boots_name, sizeof(boots->boots_name), default_node, (xmlChar*)"skin");
4209 			if (*boots->model_name=='\0')
4210 			{
4211 				get_item_string_value(boots->model_name, sizeof(boots->model_name), default_node, (xmlChar*)"mesh");
4212 				boots->mesh_index= cal_load_mesh(act, boots->model_name, "boots");
4213 			}
4214 		}
4215 	}
4216 
4217 	// check the critical information
4218 	actor_check_string(act, "boots", "boots", boots->boots_name);
4219 	actor_check_string(act, "boots", "model", boots->model_name);
4220 	actor_check_int(act, "boots", "mesh", boots->mesh_index);
4221 
4222 	return ok;
4223 }
4224 
4225 //Searches if a mesh is already loaded- TODO:MAKE THIS BETTER
cal_search_mesh(actor_types * act,const char * fn,const char * kind)4226 int cal_search_mesh (actor_types *act, const char *fn, const char *kind)
4227 {
4228 	int i;
4229 
4230 	if (kind == NULL)
4231 	{
4232 		return -1;
4233 	}
4234 	else if (act->head && strcmp (kind, "head") == 0)
4235 	{
4236 		for (i = 0; i < actor_part_sizes[ACTOR_HEAD_SIZE]; i++)
4237 			if (strcmp (fn, act->head[i].model_name) == 0 && act->head[i].mesh_index != -1)
4238 				return act->head[i].mesh_index;
4239 	}
4240 	else if (act->shirt && strcmp (kind, "shirt") == 0)
4241 	{
4242 		for (i = 0; i < actor_part_sizes[ACTOR_SHIRT_SIZE]; i++)
4243 		{
4244 			if (strcmp (fn, act->shirt[i].model_name) == 0 && act->shirt[i].mesh_index != -1)
4245 				return act->shirt[i].mesh_index;
4246 		}
4247 	}
4248 	else if (act->legs && strcmp (kind, "legs") == 0)
4249 	{
4250 		for (i = 0; i < actor_part_sizes[ACTOR_LEGS_SIZE]; i++)
4251 		{
4252 			if (strcmp (fn, act->legs[i].model_name) == 0 && act->legs[i].mesh_index != -1)
4253 				return act->legs[i].mesh_index;
4254 		}
4255 	}
4256 	else if (act->boots && strcmp (kind, "boots") == 0)
4257 	{
4258 		for (i = 0; i < actor_part_sizes[ACTOR_BOOTS_SIZE]; i++)
4259 		{
4260 			if (strcmp (fn, act->boots[i].model_name) == 0 && act->boots[i].mesh_index != -1)
4261 				return act->boots[i].mesh_index;
4262 		}
4263 	}
4264 	else if (act->cape && strcmp (kind, "cape") == 0)
4265 	{
4266 		for (i = 0; i < actor_part_sizes[ACTOR_CAPE_SIZE]; i++)
4267 		{
4268 			if (strcmp (fn, act->cape[i].model_name) == 0 && act->cape[i].mesh_index != -1)
4269 				return act->cape[i].mesh_index;
4270 		}
4271 	}
4272 	else if (act->helmet && strcmp (kind, "helmet") == 0)
4273 	{
4274 		for (i = 0; i < actor_part_sizes[ACTOR_HELMET_SIZE]; i++)
4275 		{
4276 			if (strcmp (fn, act->helmet[i].model_name) == 0 && act->helmet[i].mesh_index != -1)
4277 				return act->helmet[i].mesh_index;
4278 		}
4279 	}
4280 	else if (act->neck && strcmp (kind, "neck") == 0)
4281 	{
4282 		for (i = 0; i < actor_part_sizes[ACTOR_NECK_SIZE]; i++)
4283 		{
4284 			if (strcmp (fn, act->neck[i].model_name) == 0 && act->neck[i].mesh_index != -1)
4285 				return act->neck[i].mesh_index;
4286 		}
4287 	}
4288 	else if (act->shield && strcmp (kind, "shield") == 0)
4289 	{
4290 		for (i = 0; i < actor_part_sizes[ACTOR_SHIELD_SIZE]; i++)
4291 		{
4292 			if (strcmp (fn, act->shield[i].model_name) == 0 && act->shield[i].mesh_index != -1)
4293 				return act->shield[i].mesh_index;
4294 		}
4295 	}
4296 	else if (act->weapon && strcmp (kind, "weapon") == 0)
4297 	{
4298 		for (i = 0; i < actor_part_sizes[ACTOR_WEAPON_SIZE]; i++)
4299 		{
4300 			if (strcmp (fn, act->weapon[i].model_name) == 0 && act->weapon[i].mesh_index != -1)
4301 				return act->weapon[i].mesh_index;
4302 		}
4303 	}
4304 
4305 	return -1;
4306 }
4307 
4308 //Loads a Cal3D mesh
cal_load_mesh(actor_types * act,const char * fn,const char * kind)4309 int cal_load_mesh(actor_types *act, const char *fn, const char *kind)
4310 {
4311 	int res;
4312 	struct CalCoreMesh *mesh;
4313 
4314 	if (fn==0) return -1;
4315 	if (strlen(fn)==0) return -1;
4316 	if (act->coremodel==NULL) return -1;
4317 	if (kind != NULL)
4318 	{
4319 		res = cal_search_mesh (act, fn, kind);
4320 		if (res != -1) return res;
4321 	}
4322 
4323 	//Load coremesh
4324 	res=CalCoreModel_ELLoadCoreMesh(act->coremodel,fn);
4325 
4326 	//Scale coremesh
4327 	if (res >= 0) {
4328 		mesh=CalCoreModel_GetCoreMesh(act->coremodel,res);
4329 		if ((mesh)&&(act->mesh_scale!=1.0)) CalCoreMesh_Scale(mesh,act->mesh_scale);
4330 	} else {
4331 		LOG_ERROR("Cal3d error: %s: %s\n", fn, CalError_GetLastErrorDescription());
4332 	}
4333 
4334 	return res;
4335 }
4336 
cal_load_weapon_mesh(actor_types * act,const char * fn,const char * kind)4337 int cal_load_weapon_mesh (actor_types *act, const char *fn, const char *kind)
4338 {
4339 	int res;
4340 	struct CalCoreMesh *mesh;
4341 
4342 	if (fn==0) return -1;
4343 	if (strlen(fn)==0) return -1;
4344 	if (act->coremodel==NULL) return -1;
4345 
4346 	if (kind != NULL)
4347 	{
4348 		res = cal_search_mesh (act, fn, kind);
4349 		if (res!=-1) return res;
4350 	}
4351 
4352 	//Load coremesh
4353 	res=CalCoreModel_ELLoadCoreMesh(act->coremodel,fn);
4354 
4355 	//Scale coremesh
4356 	if (res>=0) {
4357 		mesh=CalCoreModel_GetCoreMesh(act->coremodel,res);
4358 		if ((mesh)&&(act->skel_scale!=1.0)) CalCoreMesh_Scale(mesh,act->skel_scale);
4359 	} else {
4360 		LOG_ERROR("Cal3d error: %s: %s\n", fn, CalError_GetLastErrorDescription());
4361 	}
4362 
4363 	return res;
4364 }
4365 
parse_actor_nodes(actor_types * act,const xmlNode * cfg,const xmlNode * defaults)4366 int parse_actor_nodes(actor_types *act, const xmlNode *cfg, const xmlNode *defaults)
4367 {
4368 	char name[256];
4369 	const xmlNode *item;
4370 	int ok= 1;
4371 
4372 	for (item=cfg->children; item; item=item->next)
4373 	{
4374 		if(item->type == XML_ELEMENT_NODE)
4375 		{
4376 			safe_strncpy(name, (const char*)item->name, sizeof(name));
4377 			my_tolower(name);
4378 
4379 			if (!strcmp(name, "ghost")) {
4380 				act->ghost= get_bool_value(item);
4381 			} else if (!strcmp(name, "skin")) {
4382 				get_string_value(act->skin_name, sizeof (act->skin_name), item);
4383 			} else if (!strcmp(name, "mesh")) {
4384 				get_string_value(act->file_name, sizeof (act->file_name), item);
4385 			} else if (!strcmp(name, "actor_scale")) {
4386 				act->actor_scale= get_float_value(item);
4387 			} else if (!strcmp(name, "scale")) {
4388 				act->scale= get_float_value(item);
4389 			} else if (!strcmp(name, "mesh_scale")) {
4390 				act->mesh_scale= get_float_value(item);
4391 			} else if (!strcmp(name, "bone_scale")) {
4392 				act->skel_scale= get_float_value(item);
4393 			} else if (!strcmp(name, "skeleton")) {
4394 				char skeleton_name[MAX_FILE_PATH];
4395 				get_string_value(skeleton_name, sizeof(skeleton_name), item);
4396 				act->coremodel= CalCoreModel_New("Model");
4397 				if(!CalCoreModel_ELLoadCoreSkeleton(act->coremodel, skeleton_name)) {
4398 					LOG_ERROR("Cal3d error: %s: %s\n", skeleton_name, CalError_GetLastErrorDescription());
4399 					act->skeleton_type = -1;
4400 				}
4401 				else {
4402 					act->skeleton_type = get_skeleton(act->coremodel, skeleton_name);
4403 				}
4404 			} else if (!strcmp(name, "walk_speed")) { // unused
4405 				act->walk_speed= get_float_value(item);
4406 			} else if (!strcmp(name, "run_speed")) { // unused
4407 				act->run_speed= get_float_value(item);
4408 			} else if (!strcmp(name, "step_duration")) {
4409 				act->step_duration = get_int_value(item);
4410 			} else if (!strcmp(name, "defaults")) {
4411 				defaults= item;
4412 			} else if (!strcmp(name, "frames")) {
4413 				ok &= parse_actor_frames(act, item->children, defaults);
4414 			} else if (!strcmp(name, "shirt")) {
4415 				ok &= parse_actor_shirt(act, item, defaults);
4416 			} else if (!strcmp(name, "hskin")) {
4417 				ok &= parse_actor_skin(act, item, defaults);
4418 			} else if (!strcmp(name, "hair")) {
4419 				ok &= parse_actor_hair(act, item, defaults);
4420 			} else if (!strcmp(name, "eyes")) {
4421 				ok &= parse_actor_eyes(act, item, defaults);
4422 			} else if (!strcmp(name, "boots")) {
4423 				ok &= parse_actor_boots(act, item, defaults);
4424 			} else if (!strcmp(name, "legs")) {
4425 				ok &= parse_actor_legs(act, item, defaults);
4426 			} else if (!strcmp(name, "cape")) {
4427 				ok &= parse_actor_cape(act, item, defaults);
4428 			} else if (!strcmp(name, "head")) {
4429 				ok &= parse_actor_head(act, item, defaults);
4430 			} else if (!strcmp(name, "shield")) {
4431 				ok &= parse_actor_shield(act, item, defaults);
4432 			} else if (!strcmp(name, "weapon")) {
4433 				ok &= parse_actor_weapon(act, item, defaults);
4434 			} else if (!strcmp(name, "helmet")) {
4435 				ok &= parse_actor_helmet(act, item, defaults);
4436 			} else if (!strcmp(name, "neck")) {
4437 				ok &= parse_actor_neck(act, item, defaults);
4438 			} else if (!strcmp(name, "sounds")) {
4439 #ifdef NEW_SOUND
4440 				ok &= parse_actor_sounds(act, item->children);
4441 #endif	//NEW_SOUND
4442 			} else if (!strcmp(name, "actor_attachment")) {
4443 				int id = get_int_property(item, "id");
4444 				if (id < 0 || id >= MAX_ACTOR_DEFS) {
4445 					LOG_ERROR("Unable to find id/property node %s\n", item->name);
4446 					ok = 0;
4447 				}
4448 				else
4449 					ok &= parse_actor_attachment(act, item, id);
4450 			} else {
4451 				LOG_ERROR("Unknown actor attribute \"%s\"", item->name);
4452 				ok= 0;
4453 			}
4454 		} else if (item->type == XML_ENTITY_REF_NODE) {
4455 			ok &= parse_actor_nodes(act, item->children, defaults);
4456 		}
4457 	}
4458 	return ok;
4459 }
4460 
parse_actor_script(const xmlNode * cfg)4461 int parse_actor_script(const xmlNode *cfg)
4462 {
4463 	int ok, act_idx, i;
4464 	int j;
4465 	actor_types *act;
4466 	struct CalCoreSkeleton *skel;
4467 
4468 	if(cfg == NULL || cfg->children == NULL) return 0;
4469 
4470 	act_idx= get_int_property(cfg, "id");
4471 /*	if(act_idx < 0){
4472 		act_idx= get_property(cfg, "type", "actor type", actor_type_dict);
4473 	}
4474 */
4475 	if (act_idx < 0 || act_idx >= MAX_ACTOR_DEFS){
4476 		char	str[256];
4477 		char    name[256];
4478 
4479 		safe_strncpy(name, get_string_property(cfg, "type"), sizeof(name));
4480 		safe_snprintf(str, sizeof(str), "Data Error in %s(%d): Actor ID out of range %d",
4481 			name, act_idx, act_idx
4482 		);
4483 		LOG_ERROR(str);
4484 		return 0;
4485 	}
4486 
4487 	act= &(actors_defs[act_idx]);
4488 	// watch for loading an actor more then once
4489 	if(act->actor_type > 0 || *act->actor_name){
4490 		char	str[256];
4491 		char    name[256];
4492 
4493 		safe_strncpy(name, get_string_property(cfg, "type"), sizeof(name));
4494 		safe_snprintf(str, sizeof(str), "Data Error in %s(%d): Already loaded %s(%d)",
4495 			name, act_idx, act->actor_name, act->actor_type
4496 		);
4497 		LOG_ERROR(str);
4498 	}
4499 	act->actor_type= act_idx;	// memorize the ID & name to help in debugging
4500 	safe_strncpy(act->actor_name, get_string_property(cfg, "type"), sizeof(act->actor_name));
4501 	actor_check_string(act, "actor", "name", act->actor_name);
4502 
4503 	//Initialize Cal3D settings
4504 	act->coremodel= NULL;
4505 	act->actor_scale= 1.0;
4506 	act->scale= 1.0;
4507 	act->mesh_scale= 1.0;
4508 	act->skel_scale= 1.0;
4509 	act->group_count= 0;
4510 	for (i=0; i<16; ++i) {
4511 		safe_strncpy(act->idle_group[i].name, "", sizeof(act->idle_group[i].name));
4512 		act->idle_group[i].count= 0;
4513 	}
4514 
4515 	for (i = 0; i < NUM_ACTOR_FRAMES; i++) {
4516 		act->cal_frames[i].anim_index= -1;
4517 #ifdef NEW_SOUND
4518 		act->cal_frames[i].sound= -1;
4519 #endif // NEW_SOUND
4520 	}
4521 #ifdef NEW_SOUND
4522 	act->battlecry.sound = -1;
4523 #endif // NEW_SOUND
4524 
4525 	for (i = 0; i < MAX_ACTOR_DEFS; ++i)
4526 	{
4527 		for (j = 0; j < NUM_ATTACHED_ACTOR_FRAMES; j++) {
4528 			attached_actors_defs[act_idx].actor_type[i].cal_frames[j].anim_index = -1;
4529 #ifdef NEW_SOUND
4530 			attached_actors_defs[act_idx].actor_type[i].cal_frames[j].sound = -1;
4531 #endif // NEW_SOUND
4532 		}
4533 	}
4534 
4535 	act->step_duration = DEFAULT_STEP_DURATION; // default value
4536 
4537 	ok= parse_actor_nodes(act, cfg, NULL);
4538 
4539 	// TODO: add error checking for missing actor information
4540 
4541 	//Actor def parsed, now setup the coremodel
4542 	if (act->coremodel!=NULL)
4543 	{
4544 		skel=CalCoreModel_GetCoreSkeleton(act->coremodel);
4545 		if(skel){
4546 			CalCoreSkeleton_Scale(skel,act->skel_scale);
4547 		}
4548 
4549 		// If this not an enhanced actor, load the single mesh and exit
4550 		if(!act->head || strcmp (act->head[0].model_name, "") == 0)
4551 		{
4552 			act->shirt = (shirt_part*)calloc(actor_part_sizes[ACTOR_SHIRT_SIZE], sizeof(shirt_part));
4553 			act->shirt[0].mesh_index= cal_load_mesh(act, act->file_name, NULL); //save the single meshindex as torso
4554 		}
4555 		if (use_animation_program)
4556 		{
4557 			build_buffers(act);
4558 		}
4559 	}
4560 
4561 	return ok;
4562 }
4563 
parse_actor_defs(const xmlNode * node)4564 int parse_actor_defs(const xmlNode *node)
4565 {
4566 	const xmlNode *def;
4567 	int ok = 1;
4568 
4569 	for (def = node->children; def; def = def->next)
4570 	{
4571 		if (def->type == XML_ELEMENT_NODE)
4572 		{
4573 			if (xmlStrcasecmp (def->name, (xmlChar*)"actor") == 0)
4574 			{
4575 				ok &= parse_actor_script (def);
4576 			}
4577 			else
4578 			{
4579 				LOG_ERROR("parse error: actor or include expected");
4580 				ok = 0;
4581 			}
4582 		}
4583 		else if (def->type == XML_ENTITY_REF_NODE)
4584 		{
4585 			ok &= parse_actor_defs (def->children);
4586 		}
4587 	}
4588 
4589 	return ok;
4590 }
4591 
4592 #ifdef EXT_ACTOR_DICT
parse_skin_colours(const xmlNode * node)4593 int parse_skin_colours(const xmlNode *node)
4594 {
4595 	const xmlNode *data;
4596 	int ok = 1, i;
4597 
4598 	num_skin_colors = 0;
4599 	for (i = 0; i < MAX_SKIN_COLORS; i++) {
4600 		skin_color_dict[i].index = 0;
4601 		strcpy(skin_color_dict[i].desc, "");
4602 	}
4603 	for (data = node->children; data; data = data->next) {
4604 		if (data->type == XML_ELEMENT_NODE) {
4605 			if (xmlStrcasecmp(data->name, (xmlChar*)"skin") == 0) {
4606 				safe_strncpy(skin_color_dict[num_skin_colors].desc, get_string_property(data, "color"), sizeof(skin_color_dict[num_skin_colors].desc));
4607 				skin_color_dict[num_skin_colors].index = get_int_value(data);
4608 				num_skin_colors++;
4609 			} else {
4610 				LOG_ERROR("parse error: skin or include expected");
4611 				ok = 0;
4612 			}
4613 		} else if (data->type == XML_ENTITY_REF_NODE) {
4614 			ok &= parse_skin_colours(data->children);
4615 		}
4616 	}
4617 
4618 	return ok;
4619 }
4620 
parse_glow_modes(const xmlNode * node)4621 int parse_glow_modes(const xmlNode *node)
4622 {
4623 	const xmlNode *data;
4624 	int ok = 1, i;
4625 
4626 	num_glow_modes = 0;
4627 	for (i = 0; i < MAX_GLOW_MODES; i++) {
4628 		glow_mode_dict[i].index = 0;
4629 		strcpy(glow_mode_dict[i].desc, "");
4630 	}
4631 	for (data = node->children; data; data = data->next) {
4632 		if (data->type == XML_ELEMENT_NODE) {
4633 			if (xmlStrcasecmp(data->name, (xmlChar*)"glow") == 0) {
4634 				safe_strncpy(glow_mode_dict[num_glow_modes].desc, get_string_property(data, "mode"), sizeof(glow_mode_dict[num_glow_modes].desc));
4635 				glow_mode_dict[num_glow_modes].index = get_int_value(data);
4636 				num_glow_modes++;
4637 			} else {
4638 				LOG_ERROR("parse error: glow or include expected");
4639 				ok = 0;
4640 			}
4641 		} else if (data->type == XML_ENTITY_REF_NODE) {
4642 			ok &= parse_glow_modes(data->children);
4643 		}
4644 	}
4645 
4646 	return ok;
4647 }
4648 
parse_head_numbers(const xmlNode * node)4649 int parse_head_numbers(const xmlNode *node)
4650 {
4651 	const xmlNode *data;
4652 	int ok = 1, i;
4653 
4654 	num_head_numbers = 0;
4655 	for (i = 0; i < MAX_HEAD_NUMBERS; i++) {
4656 		head_number_dict[i].index = 0;
4657 		strcpy(head_number_dict[i].desc, "");
4658 	}
4659 	for (data = node->children; data; data = data->next) {
4660 		if (data->type == XML_ELEMENT_NODE) {
4661 			if (xmlStrcasecmp(data->name, (xmlChar*)"head") == 0) {
4662 				safe_strncpy(head_number_dict[num_head_numbers].desc, get_string_property(data, "number"), sizeof(head_number_dict[num_head_numbers].desc));
4663 				head_number_dict[num_head_numbers].index = get_int_value(data);
4664 				num_head_numbers++;
4665 			} else {
4666 				LOG_ERROR("parse error: head or include expected");
4667 				ok = 0;
4668 			}
4669 		} else if (data->type == XML_ENTITY_REF_NODE) {
4670 			ok &= parse_head_numbers(data->children);
4671 		}
4672 	}
4673 
4674 	return ok;
4675 }
4676 
parse_actor_dict(const xmlNode * node)4677 int parse_actor_dict(const xmlNode *node)
4678 {
4679 	const xmlNode *data;
4680 	int ok = 1;
4681 
4682 	for (data = node->children; data; data = data->next) {
4683 		if (data->type == XML_ELEMENT_NODE) {
4684 			if (xmlStrcasecmp(data->name, (xmlChar*)"skin_colors") == 0) {
4685 				ok &= parse_skin_colours(data);
4686 			} else if (xmlStrcasecmp(data->name, (xmlChar*)"glow_modes") == 0) {
4687 				ok &= parse_glow_modes(data);
4688 			} else if (xmlStrcasecmp(data->name, (xmlChar*)"head_numbers") == 0) {
4689 				ok &= parse_head_numbers(data);
4690 			} else {
4691 				LOG_ERROR("parse error: skin_colors, glow_modes, head_numbers or include expected");
4692 				ok = 0;
4693 			}
4694 		} else if (data->type == XML_ENTITY_REF_NODE) {
4695 			ok &= parse_actor_dict(data->children);
4696 		}
4697 	}
4698 
4699 	return ok;
4700 }
4701 
parse_actor_part_sizes(const xmlNode * node)4702 int parse_actor_part_sizes(const xmlNode *node)
4703 {
4704 	const xmlNode *data;
4705 	int ok = 1;
4706 	char str[20];
4707 
4708 	for (data = node->children; data; data = data->next) {
4709 		if (data->type == XML_ELEMENT_NODE) {
4710 			if (xmlStrcasecmp(data->name, (xmlChar*)"max") == 0) {
4711 				safe_strncpy(str, get_string_property(data, "part"), sizeof(str));
4712 				if (!strcasecmp(str, "head")) {
4713 					actor_part_sizes[ACTOR_HEAD_SIZE] = get_int_value(data);
4714 				} else if (!strcasecmp(str, "shield")) {
4715 					actor_part_sizes[ACTOR_SHIELD_SIZE] = get_int_value(data);
4716 				} else if (!strcasecmp(str, "cape")) {
4717 					actor_part_sizes[ACTOR_CAPE_SIZE] = get_int_value(data);
4718 				} else if (!strcasecmp(str, "helmet")) {
4719 					actor_part_sizes[ACTOR_HELMET_SIZE] = get_int_value(data);
4720 				} else if (!strcasecmp(str, "neck")) {
4721 					actor_part_sizes[ACTOR_NECK_SIZE] = get_int_value(data);
4722 				} else if (!strcasecmp(str, "weapon")) {
4723 					actor_part_sizes[ACTOR_WEAPON_SIZE] = get_int_value(data);
4724 				} else if (!strcasecmp(str, "shirt")) {
4725 					actor_part_sizes[ACTOR_SHIRT_SIZE] = get_int_value(data);
4726 				} else if (!strcasecmp(str, "skin")) {
4727 					actor_part_sizes[ACTOR_SKIN_SIZE] = get_int_value(data);
4728 				} else if (!strcasecmp(str, "hair")) {
4729 					actor_part_sizes[ACTOR_HAIR_SIZE] = get_int_value(data);
4730 				} else if (!strcasecmp(str, "eyes")) {
4731 					actor_part_sizes[ACTOR_EYES_SIZE] = get_int_value(data);
4732 				} else if (!strcasecmp(str, "boots")) {
4733 					actor_part_sizes[ACTOR_BOOTS_SIZE] = get_int_value(data);
4734 				} else if (!strcasecmp(str, "legs")) {
4735 					actor_part_sizes[ACTOR_LEGS_SIZE] = get_int_value(data);
4736 				}
4737 			} else {
4738 				LOG_ERROR("parse error: max or include expected");
4739 				ok = 0;
4740 			}
4741 		} else if (data->type == XML_ENTITY_REF_NODE) {
4742 			ok &= parse_actor_part_sizes(data->children);
4743 		}
4744 	}
4745 
4746 	return ok;
4747 }
4748 
parse_actor_data(const xmlNode * node)4749 int parse_actor_data(const xmlNode *node)
4750 {
4751 	const xmlNode *data;
4752 	int ok = 1;
4753 	static int dict = 0, parts = 0;
4754 
4755 	for (data = node->children; data; data = data->next) {
4756 		if (data->type == XML_ELEMENT_NODE) {
4757 			if (xmlStrcasecmp(data->name, (xmlChar*)"actors") == 0) {
4758 				// Check we have parsed both the actor dict and part sizes already!!
4759 				if (parts && dict)
4760 					ok &= parse_actor_defs(data);
4761 				else
4762 				{
4763 					LOG_ERROR("parse error: actor_dict (%d) and actor_part_maximums (%d) *must* be parsed before actors", dict, parts);
4764 					ok = 0;
4765 				}
4766 			} else if (xmlStrcasecmp(data->name, (xmlChar*)"actor_dict") == 0) {
4767 				ok &= dict = parse_actor_dict(data);
4768 			} else if (xmlStrcasecmp(data->name, (xmlChar*)"actor_part_maximums") == 0) {
4769 				ok &= parts = parse_actor_part_sizes(data);
4770 			} else {
4771 				LOG_ERROR("parse error: actors, actor_dict, actor_part_maximums or include expected");
4772 				ok = 0;
4773 			}
4774 		} else if (data->type == XML_ENTITY_REF_NODE) {
4775 			ok &= parse_actor_data(data->children);
4776 		}
4777 	}
4778 
4779 	return ok;
4780 }
4781 #endif // EXT_ACTOR_DICT
4782 
read_actor_defs(const char * dir,const char * index)4783 int read_actor_defs (const char *dir, const char *index)
4784 {
4785 	const xmlNode *root;
4786 	xmlDoc *doc;
4787 	char fname[120];
4788 	int ok = 1;
4789 
4790 	safe_snprintf (fname, sizeof(fname), "%s/%s", dir, index);
4791 
4792 	doc = xmlReadFile (fname, NULL, XML_PARSE_NOENT);
4793 	if (doc == NULL) {
4794 		LOG_ERROR("Unable to read actor definition file %s", fname);
4795 		return 0;
4796 	}
4797 
4798 	root = xmlDocGetRootElement (doc);
4799 	if (root == NULL) {
4800 		LOG_ERROR("Unable to parse actor definition file %s", fname);
4801 		ok = 0;
4802 #ifndef EXT_ACTOR_DICT
4803 	} else if (xmlStrcasecmp (root->name, (xmlChar*)"actors") != 0) {
4804 		LOG_ERROR("Unknown key \"%s\" (\"actors\" expected).", root->name);
4805 #else // EXT_ACTOR_DICT
4806 	} else if (xmlStrcasecmp (root->name, (xmlChar*)"actor_data") != 0) {
4807 		LOG_ERROR("Unknown key \"%s\" (\"actor_data\" expected).", root->name);
4808 #endif // EXT_ACTOR_DICT
4809 		ok = 0;
4810 	} else {
4811 #ifndef EXT_ACTOR_DICT
4812 		ok = parse_actor_defs (root);
4813 #else // EXT_ACTOR_DICT
4814 		ok = parse_actor_data (root);
4815 #endif // EXT_ACTOR_DICT
4816 	}
4817 
4818 	xmlFreeDoc (doc);
4819 	return ok;
4820 }
4821 
init_actor_defs()4822 void init_actor_defs()
4823 {
4824 	// initialize the whole thing to zero
4825 	memset (actors_defs, 0, sizeof (actors_defs));
4826 	memset (attached_actors_defs, 0, sizeof (attached_actors_defs));
4827 	set_invert_v_coord();
4828 	read_actor_defs ("actor_defs", "actor_defs.xml");
4829 }
4830 
free_actor_defs()4831 void free_actor_defs()
4832 {
4833 	int i;
4834 	for (i=0; i<MAX_ACTOR_DEFS; i++)
4835 	{
4836 		if (actors_defs[i].head)
4837 			free(actors_defs[i].head);
4838 		if (actors_defs[i].shield)
4839 			free(actors_defs[i].shield);
4840 		if (actors_defs[i].cape)
4841 			free(actors_defs[i].cape);
4842 		if (actors_defs[i].helmet)
4843 			free(actors_defs[i].helmet);
4844 		if (actors_defs[i].neck)
4845 			free(actors_defs[i].neck);
4846 		if (actors_defs[i].weapon)
4847 			free(actors_defs[i].weapon);
4848 		if (actors_defs[i].shirt)
4849 			free(actors_defs[i].shirt);
4850 		if (actors_defs[i].skin)
4851 			free(actors_defs[i].skin);
4852 		if (actors_defs[i].hair)
4853 			free(actors_defs[i].hair);
4854 		if (actors_defs[i].boots)
4855 			free(actors_defs[i].boots);
4856 		if (actors_defs[i].legs)
4857 			free(actors_defs[i].legs);
4858 		if (actors_defs[i].eyes)
4859 			free(actors_defs[i].eyes);
4860 		if (actors_defs[i].hardware_model)
4861 			clear_buffers(&actors_defs[i]);
4862 		CalCoreModel_Delete(actors_defs[i].coremodel);
4863 	}
4864 }
4865