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