1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * FrOslew.c
21  *
22  * $Source: n:/project/cit/src/RCS/froslew.c $
23  * $Revision: 1.8 $
24  * $Author: dc $
25  * $Date: 1994/04/10 05:34:29 $
26  *
27  * Citadel Renderer
28  *  object slew system controllers/prototypes/vars
29  *
30  * $Log: froslew.c $
31  * Revision 1.8  1994/04/10  05:34:29  dc
32  * hack return codes to avoid move_to teleport and physics vector reset...
33  *
34  * Revision 1.7  1994/04/10  05:15:41  dc
35  * support for cyberman, vfx1, other 6d control structure, inc. HEAD_H
36  *
37  * Revision 1.6  1994/01/02  17:12:02  dc
38  * Initial revision
39  *
40  * Revision 1.5  1993/12/05  05:43:57  mahk
41  * Fixed player height thing for slew mode.
42  *
43  * Revision 1.4  1993/11/04  16:09:50  dc
44  * fix flat floor slewing
45  *
46  * Revision 1.3  1993/09/14  05:41:49  dc
47  * new fr/camera regieme
48  *
49  * Revision 1.2  1993/09/05  20:54:16  dc
50  * new regieme for real, or at least more so
51  *
52  * Revision 1.1  1993/09/05  20:21:41  dc
53  * Initial revision
54  *
55  */
56 
57 #define __FROSLEW_SRC
58 #include "fauxrint.h"
59 #include "froslew.h"
60 #ifndef __RENDTEST__
61 #include "objsim.h"
62 #endif
63 #include "map.h"
64 #include "tilename.h"
65 #include "mapflags.h"
66 
67 int32_t eye_mods[3] = {0, 0, 0};
68 
69 // prototype
70 int32_t *fr_objslew_obj_to_list(int32_t *flist, Obj *cobj, int count);
71 Obj *fr_objslew_list_to_obj(int32_t *flist, Obj *cobj, int count);
72 
fr_objslew_obj_to_list(int32_t * flist,Obj * cobj,int count)73 int32_t *fr_objslew_obj_to_list(int32_t *flist, Obj *cobj, int count) {
74     switch (count - 1) {
75     case 5:
76         flist[5] = (cobj->loc.b << 8);
77     case 4:
78         flist[4] = (cobj->loc.p << 8);
79     case 3:
80         flist[3] = (cobj->loc.h << 8);
81     case 2:
82         flist[2] = (cobj->loc.z << SLOPE_SHIFT_D);
83     default:
84     case 1:
85         flist[1] = cobj->loc.y;
86     case 0:
87         flist[0] = cobj->loc.x;
88         break;
89     }
90     return flist;
91 }
92 
fr_objslew_list_to_obj(int32_t * flist,Obj * cobj,int count)93 Obj *fr_objslew_list_to_obj(int32_t *flist, Obj *cobj, int count) {
94     switch (count - 1) {
95     case 5:
96         cobj->loc.b = (flist[5] >> 8);
97     case 4:
98         cobj->loc.p = (flist[4] >> 8);
99     case 3:
100         cobj->loc.h = (flist[3] >> 8);
101     case 2:
102         cobj->loc.z = (flist[2] >> SLOPE_SHIFT_D);
103     default:
104     case 1:
105         cobj->loc.y = flist[1];
106     case 0:
107         cobj->loc.x = flist[0];
108         break;
109     }
110     return cobj;
111 }
112 
113 // returns whether the camera moved or not
fr_objslew_go_real_height(Obj * cobj,int32_t * eye)114 uchar fr_objslew_go_real_height(Obj *cobj, int32_t *eye) {
115     int32_t leye[3];
116     int x, y, z;
117     MapElem *o_t;
118 
119     if (cobj != NULL) {
120         eye = leye;
121         fr_objslew_obj_to_list(eye, cobj, 3);
122     }
123     x = eye[0] >> MAP_SH;
124     y = eye[1] >> MAP_SH;
125     o_t = MAP_GET_XY(x, y);
126     z = me_height_flr(o_t);
127     z *= MAP_SC >> SLOPE_SHIFT;
128     // someday should teach this about other tile types....
129     if (me_bits_mirror(o_t) != MAP_FFLAT)
130         if ((me_tiletype(o_t) >= TILE_SLOPEUP_N) && (me_tiletype(o_t) <= TILE_SLOPEUP_W)) {
131             int diff;
132             switch (me_tiletype(o_t)) {
133             case TILE_SLOPEUP_N:
134                 diff = eye[1] & MAP_MK;
135                 break;
136             case TILE_SLOPEUP_E:
137                 diff = eye[0] & MAP_MK;
138                 break;
139             case TILE_SLOPEUP_S:
140                 diff = MAP_MK - (eye[1] & MAP_MK);
141                 break;
142             case TILE_SLOPEUP_W:
143                 diff = MAP_MK - (eye[0] & MAP_MK);
144                 break;
145             }
146             z += (diff * me_param(o_t)) >> SLOPE_SHIFT;
147         }
148     // now add height of current posture...
149     eye[2] = z + PLAYER_HEIGHT / 2; /* this should probably be fixed */
150     if (cobj != NULL)
151         fr_objslew_list_to_obj(eye, cobj, 3);
152     return TRUE;
153 }
154 
fr_objslew_allowed(Obj * cobj,int32_t * eye)155 uchar fr_objslew_allowed(Obj *cobj, int32_t *eye) {
156     int x, y; // z
157     MapElem *o_t;
158 
159     if (cobj != NULL)
160         fr_objslew_obj_to_list(eye, cobj, 3);
161     x = eye[0] >> MAP_SH;
162     y = eye[1] >> MAP_SH;
163     if ((x < 0) || (x >= MAP_XSIZE) || (y < 0) || (y >= MAP_YSIZE))
164         return FALSE;
165     o_t = MAP_GET_XY(x, y);
166     if (me_tiletype(o_t) == TILE_SOLID)
167         return FALSE;
168     if (cobj != NULL)
169         fr_objslew_list_to_obj(eye, cobj, 3);
170     return TRUE;
171 }
172 
173 // to physics teleport or not
174 // should teach it not to slam all velocities!
fr_objslew_moveone(Obj * cobj,ObjID objnum,int which,int how,uchar conform)175 uchar fr_objslew_moveone(Obj *cobj, ObjID objnum, int which, int how, uchar conform) {
176     int32_t eye[4];
177     uchar valid_pos = TRUE;
178 
179     if (cobj == NULL)
180         cobj = &objs[objnum];
181     fr_objslew_obj_to_list(eye, cobj, 4);
182     switch (which) {
183     case EYE_HEADH:
184         eye_mods[0] += how * cam_slew_scale[which];
185         return valid_pos; // break;
186     case EYE_H:
187         cobj->loc.h += (how * cam_slew_scale[which]) >> 8;
188         break;
189     case EYE_RESET:
190         eye_mods[0] = eye_mods[1] = eye_mods[2] = 0;
191         return valid_pos; // break;
192     case EYE_B:
193     case EYE_P:
194         eye_mods[which - 3] += how * cam_slew_scale[which];
195         return valid_pos; // break;
196     case EYE_Z:
197         eye[2] += how << SLOPE_SHIFT_D;
198         break;
199     case EYE_Y:
200     case EYE_X: {
201         fix v[2], tot;
202         tot = how * cam_slew_scale[which];
203         fix_sincos((fixang)(eye[3] + (which == EYE_X ? 0x4000 : 0)), v + 0, v + 1);
204         eye[0] += fix_int(fix_mul(v[0], tot));
205         eye[1] += fix_int(fix_mul(v[1], tot));
206         if (conform)
207             if ((valid_pos = fr_objslew_allowed(NULL, eye)) == TRUE)
208                 fr_objslew_go_real_height(NULL, eye);
209         break;
210     }
211     }
212     fr_objslew_list_to_obj(eye, cobj, 3);
213     obj_move_to(cobj - objs, &cobj->loc, TRUE);
214     return valid_pos;
215 }
216 
217 // to physics teleport or not
218 //#pragma disable_message(202)
fr_objslew_setone(int which,int l_new)219 uchar fr_objslew_setone(int which, int l_new) {
220     switch (which) {
221     case EYE_HEADH:
222         eye_mods[0] = l_new;
223         return TRUE;
224     case EYE_H:
225         break;
226     case EYE_RESET:
227         eye_mods[0] = eye_mods[1] = eye_mods[2] = 0;
228         return TRUE;
229     case EYE_P:
230         eye_mods[1] = l_new;
231         return TRUE;
232     case EYE_B:
233         eye_mods[2] = l_new;
234         return TRUE;
235     case EYE_Z:
236     case EYE_Y:
237     case EYE_X:
238         break;
239     }
240     return TRUE;
241 }
242 //#pragma enable_message(202)
243 
244 /* KLC - not used
245 uchar fr_objslew_tele_to(Obj *, int , int )
246 {
247    return TRUE;
248 }
249 */
250