1 /* ResidualVM - A 3D game interpreter
2 *
3 * ResidualVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the AUTHORS
5 * file distributed with this source distribution.
6 *
7 * Additional copyright for this file:
8 * Copyright (C) 1999-2000 Revolution Software Ltd.
9 * This code is based on source code created by Revolution Software,
10 * used with permission.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "engines/icb/p4.h"
29 #include "engines/icb/common/px_common.h"
30 #include "engines/icb/common/px_linkeddatafile.h"
31 #include "engines/icb/mission.h"
32 #include "engines/icb/session.h"
33 #include "engines/icb/object_structs.h"
34 #include "engines/icb/debug.h"
35 #include "engines/icb/player.h"
36 #include "engines/icb/direct_input.h"
37 #include "engines/icb/barriers.h"
38 #include "engines/icb/common/px_route_barriers.h"
39 #include "engines/icb/global_objects.h"
40 #include "engines/icb/animation_mega_set.h"
41 #include "engines/icb/mission.h"
42 #include "engines/icb/res_man.h"
43
44 #include "common/textconsole.h"
45
46 namespace ICB {
47
Find_interact_marker_in_anim(__mega_set_names animation,PXreal * xoff,PXreal * zoff)48 bool8 _game_session::Find_interact_marker_in_anim(__mega_set_names animation, PXreal *xoff, PXreal *zoff) {
49 // find the first instance of the interact marker - which will be on every frame or none at all which is an error
50 // then find the offset from the feet ORG_MARKET to the INT interaction marker
51 // this difference is the relative position from the nico that the character must route to to run this animation
52 // the idea being that the animations can therefore change without any effect on the engine - its all data driven
53
54 // first check anim file will exist
55 if (!I->IsAnimTable(animation))
56 Fatal_error("Find_interact_marker_in_anim finds [%s] doesnt have a [%s] animation", object->GetName(), master_anim_name_table[animation].name);
57
58 // open the file
59 PXanim *pAnim = (PXanim *)rs_anims->Res_open(I->get_info_name(animation), I->info_name_hash[animation], I->base_path, I->base_path_hash);
60
61 // New code block
62
63 // Loop over animation frames looking for interact if it is found then
64 // take the position from where it is found
65 // i.e. replace the hard coded look on frame 0 with search for it
66 //
67 // The INTERACT marker comes in two forms
68 // INT0_TYPE : which means it was a forced export on frame 0 only, because the anim never made the INT marker visible
69 // INT_TYPE : which means it was a real export of the INT marker on the frame when the anim made the INT marker visible
70
71 PXreal x_org, z_org, unused;
72 PXFrameEnOfAnim(0, pAnim)->markers[ORG_POS].GetXYZ(&x_org, &unused, &z_org);
73
74 for (uint16 frame = 0; frame < pAnim->frame_qty; frame++) {
75 PXframe *frm = PXFrameEnOfAnim(frame, pAnim);
76 // Check the interact marker is present
77
78 if (frm->marker_qty > INT_POS) {
79 PXmarker *marker = &(frm->markers[INT_POS]);
80 uint8 mtype = (uint8)marker->GetType();
81
82 if ((INT0_TYPE == mtype) || (INT_TYPE == mtype)) {
83 // The interact marker exists
84 PXreal x_int, z_int;
85
86 marker->GetXYZ(&x_int, &unused, &z_int);
87
88 xoff[0] = x_int - x_org;
89 zoff[0] = z_int - z_org;
90
91 return (TRUE8);
92 }
93 }
94 }
95 // did not find an INT marker!
96 Message_box("Warning couldn't find INT marker for '%s' %X %s", I->get_info_name(animation), I->info_name_hash[animation], master_anim_name_table[animation].name);
97
98 xoff[0] = REAL_ZERO;
99 zoff[0] = REAL_ZERO;
100 return (TRUE8);
101
102 // This is an error and should be re-enabled, it is made a warning so implementation can continue
103 // and they can get the anims fixed as time proceeds
104 // We must then get an interaction marker put into the animation
105 }
106
Compute_target_interaction_coordinate(__mega_set_names anim,PXreal * destx,PXreal * destz)107 bool8 _game_session::Compute_target_interaction_coordinate(__mega_set_names anim, PXreal *destx, PXreal *destz) {
108 // get target coordinate
109 // this is for prop interaction
110 // used L->target_id
111
112 // we're passed TYPE of anim
113 // the type may be __CUSTOM
114
115 PXreal int_x, int_z; // for the marker
116 bool8 ret;
117 PXfloat tpan;
118
119 // get interact marker offset
120 ret = Find_interact_marker_in_anim(anim, &int_x, &int_z);
121
122 if (!ret) {
123 Zdebug("no int marker found in %s", (const char *)(I->get_info_name(anim)));
124 Fatal_error("Compute_target_interaction_coordinate: no int marker error object %s anim %s", (const char *)(L->GetName()), (const char *)(I->get_info_name(anim)));
125 }
126
127 Zdebug("INT markers %3.2f, %3.2f", int_x, int_z);
128
129 // get coord of target object and sub from it the offset from the anim
130
131 // reverse the target pan so it faces 180deg back around
132 tpan = logic_structs[M->target_id]->prop_interact_pan + HALF_TURN;
133
134 // now project the interaction offset back away from the target nico
135 // this will give us our interact coordinate
136 PXfloat ang = tpan * TWO_PI;
137 PXfloat cang = (PXfloat)PXcos(ang);
138 PXfloat sang = (PXfloat)PXsin(ang);
139
140 destx[0] = logic_structs[M->target_id]->prop_xyz.x + PXfloat2PXreal(int_x * cang + int_z * sang);
141 destz[0] = logic_structs[M->target_id]->prop_xyz.z + PXfloat2PXreal(int_z * cang - int_x * sang);
142
143 return (TRUE8);
144 }
145
Snap_to_ladder(_stair * lad,uint32 dist)146 void _game_session::Snap_to_ladder(_stair *lad, uint32 dist) {
147 // snap our coordinate to passed ladder
148 // take the ladder marker, reverse its pan, and push backward to get our coordinate
149 // sadly we need to push back by a different amount for top or bottom
150
151 PXfloat tpan;
152
153 tpan = lad->pan + HALF_TURN; // reverse the ladder nico
154
155 PXfloat ang = tpan * TWO_PI;
156 PXfloat cang = (PXfloat)PXcos(ang);
157 PXfloat sang = (PXfloat)PXsin(ang);
158
159 warning("Snap:: lad %f %f ang %f", lad->x, lad->z, (ang * 360) / FULL_TURN);
160
161 M->actor_xyz.x = lad->x + PXfloat2PXreal((PXfloat)(dist)*sang);
162 M->actor_xyz.z = lad->z + PXfloat2PXreal((PXfloat)(dist)*cang);
163
164 warning("Snap:: new pos %f %f", M->actor_xyz.x, M->actor_xyz.z);
165 }
166
167 } // End of namespace ICB
168