]> icculus.org git repositories - btb/d2x.git/blob - main/robot.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / main / robot.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Code for handling robots
17  *
18  */
19
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdio.h>
26
27 #include "dxxerror.h"
28 #include "inferno.h"
29 #include "mono.h"
30
31
32 int     N_robot_types = 0;
33 int     N_robot_joints = 0;
34
35 //      Robot stuff
36 robot_info Robot_info[MAX_ROBOT_TYPES];
37
38 #ifndef EDITOR
39 /* names "mech" through "escort" found in bitmaps.tbl */
40 char Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH] = {
41         "mech",         // medium hulk
42         "green",        // green claw, medium lifter
43         "spider",       // red spider, processing robot
44         "josh",         // class 1 drone
45         "violet",       // spike, class 2 drone
46         "clkvulc",      // cloaked class 1 driller
47         "clkmech",      // cloaked hulk
48         "brain",        // class 2 supervisor robot
49         "onearm",       // secondary lifter
50         "plasguy",      // class 1 heavy driller
51         "toaster",      // class 3 gopher robot
52         "bird",         // class 1 platform robot
53         "mislbird",     // class 2 platform robot
54         "splitpod",     // polyhedron, split pod
55         "smspider",     // baby spider
56         "miniboss",     // mini boss, fusion hulk
57         "suprmech",     // super mech, heavy hulk
58         "boss1",        // shareware boss, super hulk
59         "cloakgrn",     // cloaked lifter
60         "vulcnguy",     // vulcan guy, class 1 driller
61         "rifleman",     // toad, small hulk
62         "fourclaw",     // advanced lifter
63         "quadlaser",    // defense prototype
64         "boss2",        // bigboss, mega hulk
65         "babyplas",     // bper bot
66         "newguy",       // smelter
67         "icespidr",     // ice spindle defense robot
68         "gaussguy",     // bulk destroyer
69         "newguy2",      // trn racer
70         "newguy3",      // fox attack bot
71         "newguy4",      // sidearm
72         "newguy5",      // zeta aquilae boss
73         "newboss1",     // ?? boss2
74         "escort",       // guide bot
75         "plasguy2",     // ?? plasguy w/missiles
76         "kamikaze",     // ?? kamikaze escort
77         "itsc",         // internal tactical security control robot
78         "itd",          // internal tactical droid
79         "pest",         // portable equalizing standard transport
80         "pig",          // preliminary integration groundbot
81         "diamondclaw",  // diamond claw, second generation
82         "redhornet",    // red hornet
83         "thief",        // thief, bandit
84         "seeker",       // seeker
85         "ebandit",      // e-bandit
86         "45",           // brimspark boss
87         "46",           // quartzon boss
88         "boarshead",    // boarshead
89         "spider2",      // spider
90         "omegadefense", // omega defense spawn
91         "sidearmmodula", // sidearm modula
92         "louguard",     // lou guard
93         "52",           // baloris prime boss
94         "53",           // brimspark mini boss
95         "clkdiamondclaw", // cloaked diamond claw
96         "clksmelter",   // cloaked smelter
97         "purpleomega",  // ?? purple omegadefense
98         "smelter",      // ?? another newguy
99         "omegadefense2", // ?? another omegadefense
100         "bper",         // ?? another babyplas
101         "spider2b",     // ?? another spider2
102         "spawn",        // spawn
103         "62",           // limefrost spiral boss
104         "spawn2",       // ?? another spawn
105         "64",           // tycho brahe boss
106         "65",           // ?? a reactor?
107         /* vertigo robots, possibly not constant */
108         "compactlifter", // compact lifter
109         "fervid99",     // fervid 99
110         "fiddler",      // fiddler
111         "heavydriller2", // class 2 heavy driller
112         "smelter2",     // smelter ii
113         "max",          // maximum amplified xenophobe
114         "sniperng",     // sniper ng
115         "logikill",     // codename: logikill
116         "canary",       // canary
117         "75",           // vertigo boss 1
118         "76",           // vertigo boss 2
119         "spike",        // s.p.i.k.e.
120 };
121 #endif
122
123 //Big array of joint positions.  All robots index into this array
124
125 #define deg(a) ((int) (a) * 32768 / 180)
126
127 //test data for one robot
128 jointpos Robot_joints[MAX_ROBOT_JOINTS] = {
129
130 //gun 0
131         {2,{deg(-30),0,0}},         //rest (2 joints)
132         {3,{deg(-40),0,0}},
133
134         {2,{deg(0),0,0}},           //alert
135         {3,{deg(0),0,0}},
136
137         {2,{deg(0),0,0}},           //fire
138         {3,{deg(0),0,0}},
139
140         {2,{deg(50),0,0}},          //recoil
141         {3,{deg(-50),0,0}},
142
143         {2,{deg(10),0,deg(70)}},    //flinch
144         {3,{deg(0),deg(20),0}},
145
146 //gun 1
147         {4,{deg(-30),0,0}},         //rest (2 joints)
148         {5,{deg(-40),0,0}},
149
150         {4,{deg(0),0,0}},           //alert
151         {5,{deg(0),0,0}},
152
153         {4,{deg(0),0,0}},           //fire
154         {5,{deg(0),0,0}},
155
156         {4,{deg(50),0,0}},          //recoil
157         {5,{deg(-50),0,0}},
158
159         {4,{deg(20),0,deg(-50)}},   //flinch
160         {5,{deg(0),0,deg(20)}},
161
162 //rest of body (the head)
163
164         {1,{deg(70),0,0}},          //rest (1 joint, head)
165
166         {1,{deg(0),0,0}},           //alert
167
168         {1,{deg(0),0,0}},           //fire
169
170         {1,{deg(0),0,0}},           //recoil
171
172         {1,{deg(-20),deg(15),0}},   //flinch
173
174 };
175
176 //given an object and a gun number, return position in 3-space of gun
177 //fills in gun_point
178 void calc_gun_point(vms_vector *gun_point,object *obj,int gun_num)
179 {
180         polymodel *pm;
181         robot_info *r;
182         vms_vector pnt;
183         vms_matrix m;
184         int mn;                         //submodel number
185
186         Assert(obj->render_type==RT_POLYOBJ || obj->render_type==RT_MORPH);
187         Assert(obj->id < N_robot_types);
188
189         r = &Robot_info[obj->id];
190         pm =&Polygon_models[r->model_num];
191
192         if (gun_num >= r->n_guns)
193         {
194                 mprintf((1, "Bashing gun num %d to 0.\n", gun_num));
195                 //Int3();
196                 gun_num = 0;
197         }
198
199 //      Assert(gun_num < r->n_guns);
200
201         pnt = r->gun_points[gun_num];
202         mn = r->gun_submodels[gun_num];
203
204         //instance up the tree for this gun
205         while (mn != 0) {
206                 vms_vector tpnt;
207
208                 vm_angles_2_matrix(&m,&obj->rtype.pobj_info.anim_angles[mn]);
209                 vm_transpose_matrix(&m);
210                 vm_vec_rotate(&tpnt,&pnt,&m);
211
212                 vm_vec_add(&pnt,&tpnt,&pm->submodel_offsets[mn]);
213
214                 mn = pm->submodel_parents[mn];
215         }
216
217         //now instance for the entire object
218
219         vm_copy_transpose_matrix(&m,&obj->orient);
220         vm_vec_rotate(gun_point,&pnt,&m);
221         vm_vec_add2(gun_point,&obj->pos);
222
223 }
224
225 //fills in ptr to list of joints, and returns the number of joints in list
226 //takes the robot type (object id), gun number, and desired state
227 int robot_get_anim_state(jointpos **jp_list_ptr,int robot_type,int gun_num,int state)
228 {
229
230         Assert(gun_num <= Robot_info[robot_type].n_guns);
231
232         *jp_list_ptr = &Robot_joints[Robot_info[robot_type].anim_states[gun_num][state].offset];
233
234         return Robot_info[robot_type].anim_states[gun_num][state].n_joints;
235
236 }
237
238
239 //for test, set a robot to a specific state
240 void set_robot_state(object *obj,int state)
241 {
242         int g,j,jo;
243         robot_info *ri;
244         jointlist *jl;
245
246         Assert(obj->type == OBJ_ROBOT);
247
248         ri = &Robot_info[obj->id];
249
250         for (g=0;g<ri->n_guns+1;g++) {
251
252                 jl = &ri->anim_states[g][state];
253
254                 jo = jl->offset;
255
256                 for (j=0;j<jl->n_joints;j++,jo++) {
257                         int jn;
258
259                         jn = Robot_joints[jo].jointnum;
260
261                         obj->rtype.pobj_info.anim_angles[jn] = Robot_joints[jo].angles;
262
263                 }
264         }
265 }
266
267 #include "mono.h"
268
269 //--unused-- int cur_state=0;
270
271 //--unused-- test_anim_states()
272 //--unused-- {
273 //--unused--    set_robot_state(&Objects[1],cur_state);
274 //--unused--
275 //--unused--    mprintf(0,"Robot in state %d\n",cur_state);
276 //--unused--
277 //--unused--    cur_state = (cur_state+1)%N_ANIM_STATES;
278 //--unused--
279 //--unused-- }
280
281 //set the animation angles for this robot.  Gun fields of robot info must
282 //be filled in.
283 void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS])
284 {
285         int m,g,state;
286         int gun_nums[MAX_SUBMODELS];                    //which gun each submodel is part of
287
288         for (m=0;m<pm->n_models;m++)
289                 gun_nums[m] = r->n_guns;                //assume part of body...
290
291         gun_nums[0] = -1;               //body never animates, at least for now
292
293         for (g=0;g<r->n_guns;g++) {
294                 m = r->gun_submodels[g];
295
296                 while (m != 0) {
297                         gun_nums[m] = g;                                //...unless we find it in a gun
298                         m = pm->submodel_parents[m];
299                 }
300         }
301
302         for (g=0;g<r->n_guns+1;g++) {
303
304                 //mprintf(0,"Gun %d:\n",g);
305
306                 for (state=0;state<N_ANIM_STATES;state++) {
307
308                         //mprintf(0," State %d:\n",state);
309
310                         r->anim_states[g][state].n_joints = 0;
311                         r->anim_states[g][state].offset = N_robot_joints;
312
313                         for (m=0;m<pm->n_models;m++) {
314                                 if (gun_nums[m] == g) {
315                                         //mprintf(0,"  Joint %d: %x %x %x\n",m,angs[state][m].pitch,angs[state][m].bank,angs[state][m].head);
316                                         Robot_joints[N_robot_joints].jointnum = m;
317                                         Robot_joints[N_robot_joints].angles = angs[state][m];
318                                         r->anim_states[g][state].n_joints++;
319                                         N_robot_joints++;
320                                         Assert(N_robot_joints < MAX_ROBOT_JOINTS);
321                                 }
322                         }
323                 }
324         }
325
326 }
327
328 #ifndef FAST_FILE_IO
329 /*
330  * reads n jointlist structs from a CFILE
331  */
332 static int jointlist_read_n(jointlist *jl, int n, CFILE *fp)
333 {
334         int i;
335
336         for (i = 0; i < n; i++) {
337                 jl[i].n_joints = cfile_read_short(fp);
338                 jl[i].offset = cfile_read_short(fp);
339         }
340         return i;
341 }
342
343 /*
344  * reads n robot_info structs from a CFILE
345  */
346 int robot_info_read_n(robot_info *ri, int n, CFILE *fp)
347 {
348         int i, j;
349
350         for (i = 0; i < n; i++) {
351                 ri[i].model_num = cfile_read_int(fp);
352                 for (j = 0; j < MAX_GUNS; j++)
353                         cfile_read_vector(&(ri[i].gun_points[j]), fp);
354                 cfread(ri[i].gun_submodels, MAX_GUNS, 1, fp);
355
356                 ri[i].exp1_vclip_num = cfile_read_short(fp);
357                 ri[i].exp1_sound_num = cfile_read_short(fp);
358
359                 ri[i].exp2_vclip_num = cfile_read_short(fp);
360                 ri[i].exp2_sound_num = cfile_read_short(fp);
361
362                 ri[i].weapon_type = cfile_read_byte(fp);
363                 ri[i].weapon_type2 = cfile_read_byte(fp);
364                 ri[i].n_guns = cfile_read_byte(fp);
365                 ri[i].contains_id = cfile_read_byte(fp);
366
367                 ri[i].contains_count = cfile_read_byte(fp);
368                 ri[i].contains_prob = cfile_read_byte(fp);
369                 ri[i].contains_type = cfile_read_byte(fp);
370                 ri[i].kamikaze = cfile_read_byte(fp);
371
372                 ri[i].score_value = cfile_read_short(fp);
373                 ri[i].badass = cfile_read_byte(fp);
374                 ri[i].energy_drain = cfile_read_byte(fp);
375
376                 ri[i].lighting = cfile_read_fix(fp);
377                 ri[i].strength = cfile_read_fix(fp);
378
379                 ri[i].mass = cfile_read_fix(fp);
380                 ri[i].drag = cfile_read_fix(fp);
381
382                 for (j = 0; j < NDL; j++)
383                         ri[i].field_of_view[j] = cfile_read_fix(fp);
384                 for (j = 0; j < NDL; j++)
385                         ri[i].firing_wait[j] = cfile_read_fix(fp);
386                 for (j = 0; j < NDL; j++)
387                         ri[i].firing_wait2[j] = cfile_read_fix(fp);
388                 for (j = 0; j < NDL; j++)
389                         ri[i].turn_time[j] = cfile_read_fix(fp);
390                 for (j = 0; j < NDL; j++)
391                         ri[i].max_speed[j] = cfile_read_fix(fp);
392                 for (j = 0; j < NDL; j++)
393                         ri[i].circle_distance[i] = cfile_read_fix(fp);
394                 cfread(ri[i].rapidfire_count, NDL, 1, fp);
395
396                 cfread(ri[i].evade_speed, NDL, 1, fp);
397
398                 ri[i].cloak_type = cfile_read_byte(fp);
399                 ri[i].attack_type = cfile_read_byte(fp);
400
401                 ri[i].see_sound = cfile_read_byte(fp);
402                 ri[i].attack_sound = cfile_read_byte(fp);
403                 ri[i].claw_sound = cfile_read_byte(fp);
404                 ri[i].taunt_sound = cfile_read_byte(fp);
405
406                 ri[i].boss_flag = cfile_read_byte(fp);
407                 ri[i].companion = cfile_read_byte(fp);
408                 ri[i].smart_blobs = cfile_read_byte(fp);
409                 ri[i].energy_blobs = cfile_read_byte(fp);
410
411                 ri[i].thief = cfile_read_byte(fp);
412                 ri[i].pursuit = cfile_read_byte(fp);
413                 ri[i].lightcast = cfile_read_byte(fp);
414                 ri[i].death_roll = cfile_read_byte(fp);
415
416                 ri[i].flags = cfile_read_byte(fp);
417                 cfread(ri[i].pad, 3, 1, fp);
418
419                 ri[i].deathroll_sound = cfile_read_byte(fp);
420                 ri[i].glow = cfile_read_byte(fp);
421                 ri[i].behavior = cfile_read_byte(fp);
422                 ri[i].aim = cfile_read_byte(fp);
423
424                 for (j = 0; j < MAX_GUNS + 1; j++)
425                         jointlist_read_n(ri[i].anim_states[j], N_ANIM_STATES, fp);
426
427                 ri[i].always_0xabcd = cfile_read_int(fp);
428         }
429         return i;
430 }
431
432 /*
433  * reads n jointpos structs from a CFILE
434  */
435 int jointpos_read_n(jointpos *jp, int n, CFILE *fp)
436 {
437         int i;
438
439         for (i = 0; i < n; i++) {
440                 jp[i].jointnum = cfile_read_short(fp);
441                 cfile_read_angvec(&jp[i].angles, fp);
442         }
443         return i;
444 }
445 #endif