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