This commit was generated by cvs2svn to compensate for changes in r2,
[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 #include <conf.h>
16
17 #include <stdio.h>
18
19 #include "error.h"
20
21 #include "inferno.h"
22
23 #include "robot.h"
24 #include "object.h"
25 #include "polyobj.h"
26 #include "mono.h"
27
28 int     N_robot_types = 0;
29 int     N_robot_joints = 0;
30
31 //      Robot stuff
32 robot_info Robot_info[MAX_ROBOT_TYPES];
33
34 //Big array of joint positions.  All robots index into this array
35
36 #define deg(a) ((int) (a) * 32768 / 180)
37
38 //test data for one robot
39 jointpos Robot_joints[MAX_ROBOT_JOINTS] = {
40
41 //gun 0
42                                         {2,{deg(-30),0,0}},             //rest (2 joints)
43                                         {3,{deg(-40),0,0}},
44
45                                         {2,{deg(0),0,0}},                       //alert
46                                         {3,{deg(0),0,0}},
47                 
48                                         {2,{deg(0),0,0}},                       //fire
49                                         {3,{deg(0),0,0}},
50                 
51                                         {2,{deg(50),0,0}},              //recoil
52                                         {3,{deg(-50),0,0}},
53                 
54                                         {2,{deg(10),0,deg(70)}},                //flinch
55                                         {3,{deg(0),deg(20),0}},
56                 
57 //gun 1
58                                         {4,{deg(-30),0,0}},             //rest (2 joints)
59                                         {5,{deg(-40),0,0}},
60
61                                         {4,{deg(0),0,0}},                       //alert
62                                         {5,{deg(0),0,0}},
63                 
64                                         {4,{deg(0),0,0}},                       //fire
65                                         {5,{deg(0),0,0}},
66                 
67                                         {4,{deg(50),0,0}},              //recoil
68                                         {5,{deg(-50),0,0}},
69                 
70                                         {4,{deg(20),0,deg(-50)}},       //flinch
71                                         {5,{deg(0),0,deg(20)}},
72                 
73 //rest of body (the head)
74
75                                         {1,{deg(70),0,0}},              //rest (1 joint, head)
76
77                                         {1,{deg(0),0,0}},                       //alert
78                 
79                                         {1,{deg(0),0,0}},                       //fire
80                 
81                                         {1,{deg(0),0,0}},                       //recoil
82
83                                         {1,{deg(-20),deg(15),0}},                       //flinch
84
85
86 };
87
88 //given an object and a gun number, return position in 3-space of gun
89 //fills in gun_point
90 void calc_gun_point(vms_vector *gun_point,object *obj,int gun_num)
91 {
92         polymodel *pm;
93         robot_info *r;
94         vms_vector pnt;
95         vms_matrix m;
96         int mn;                         //submodel number
97
98         Assert(obj->render_type==RT_POLYOBJ || obj->render_type==RT_MORPH);
99         Assert(obj->id < N_robot_types);
100
101         r = &Robot_info[obj->id];
102         pm =&Polygon_models[r->model_num];
103
104         if (gun_num >= r->n_guns)
105         {
106                 mprintf((1, "Bashing gun num %d to 0.\n", gun_num));
107                 //Int3();
108                 gun_num = 0;
109         }
110
111 //      Assert(gun_num < r->n_guns);
112
113         pnt = r->gun_points[gun_num];
114         mn = r->gun_submodels[gun_num];
115
116         //instance up the tree for this gun
117         while (mn != 0) {
118                 vms_vector tpnt;
119
120                 vm_angles_2_matrix(&m,&obj->rtype.pobj_info.anim_angles[mn]);
121                 vm_transpose_matrix(&m);
122                 vm_vec_rotate(&tpnt,&pnt,&m);
123
124                 vm_vec_add(&pnt,&tpnt,&pm->submodel_offsets[mn]);
125
126                 mn = pm->submodel_parents[mn];
127         }
128
129         //now instance for the entire object
130
131         vm_copy_transpose_matrix(&m,&obj->orient);
132         vm_vec_rotate(gun_point,&pnt,&m);
133         vm_vec_add2(gun_point,&obj->pos);
134         
135 }
136
137 //fills in ptr to list of joints, and returns the number of joints in list
138 //takes the robot type (object id), gun number, and desired state
139 int robot_get_anim_state(jointpos **jp_list_ptr,int robot_type,int gun_num,int state)
140 {
141
142         Assert(gun_num <= Robot_info[robot_type].n_guns);
143
144         *jp_list_ptr = &Robot_joints[Robot_info[robot_type].anim_states[gun_num][state].offset];
145
146         return Robot_info[robot_type].anim_states[gun_num][state].n_joints;
147
148 }
149
150
151 //for test, set a robot to a specific state
152 void set_robot_state(object *obj,int state)
153 {
154         int g,j,jo;
155         robot_info *ri;
156         jointlist *jl;
157
158         Assert(obj->type == OBJ_ROBOT);
159
160         ri = &Robot_info[obj->id];
161
162         for (g=0;g<ri->n_guns+1;g++) {
163
164                 jl = &ri->anim_states[g][state];
165
166                 jo = jl->offset;
167
168                 for (j=0;j<jl->n_joints;j++,jo++) {
169                         int jn;
170
171                         jn = Robot_joints[jo].jointnum;
172
173                         obj->rtype.pobj_info.anim_angles[jn] = Robot_joints[jo].angles;
174
175                 }
176         }
177 }
178
179 #include "mono.h"
180
181 //--unused-- int cur_state=0;
182
183 //--unused-- test_anim_states()
184 //--unused-- {
185 //--unused--    set_robot_state(&Objects[1],cur_state);
186 //--unused-- 
187 //--unused--    mprintf(0,"Robot in state %d\n",cur_state);
188 //--unused-- 
189 //--unused--    cur_state = (cur_state+1)%N_ANIM_STATES;
190 //--unused-- 
191 //--unused-- }
192
193 //set the animation angles for this robot.  Gun fields of robot info must
194 //be filled in.
195 void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES][MAX_SUBMODELS])
196 {
197         int m,g,state;
198         int gun_nums[MAX_SUBMODELS];                    //which gun each submodel is part of
199
200         for (m=0;m<pm->n_models;m++)
201                 gun_nums[m] = r->n_guns;                //assume part of body...
202
203         gun_nums[0] = -1;               //body never animates, at least for now
204
205         for (g=0;g<r->n_guns;g++) {
206                 m = r->gun_submodels[g];
207
208                 while (m != 0) {
209                         gun_nums[m] = g;                                //...unless we find it in a gun
210                         m = pm->submodel_parents[m];
211                 }
212         }
213
214         for (g=0;g<r->n_guns+1;g++) {
215
216                 //mprintf(0,"Gun %d:\n",g);
217
218                 for (state=0;state<N_ANIM_STATES;state++) {
219
220                         //mprintf(0," State %d:\n",state);
221
222                         r->anim_states[g][state].n_joints = 0;
223                         r->anim_states[g][state].offset = N_robot_joints;
224
225                         for (m=0;m<pm->n_models;m++) {
226                                 if (gun_nums[m] == g) {
227                                         //mprintf(0,"  Joint %d: %x %x %x\n",m,angs[state][m].pitch,angs[state][m].bank,angs[state][m].head);
228                                         Robot_joints[N_robot_joints].jointnum = m;
229                                         Robot_joints[N_robot_joints].angles = angs[state][m];
230                                         r->anim_states[g][state].n_joints++;
231                                         N_robot_joints++;
232                                         Assert(N_robot_joints < MAX_ROBOT_JOINTS);
233                                 }
234                         }
235                 }
236         }
237
238 }
239
240