4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
#include "system.h"
 
 
2
#include "prototyp.h"
 
 
3
#include <assert.h>
 
 
4
#include "stratdef.h"
 
 
5
#include "bh_types.h"
 
 
6
#include "weapons.h"
 
 
7
#include "kshape.h"
 
 
8
#include "pvisible.h"
 
 
9
#include <stdio.h>
 
 
10
 
 
 
11
extern int GetLoadedShapeMSL(char const * shapename);
 
 
12
extern void DrawCable(VECTORCH *centrePtr, MATRIXCH *orientationPtr);
 
 
13
extern void AssignNewSBName(STRATEGYBLOCK *sbPtr);
 
 
14
extern int CloakingPhase;
 
 
15
 
 
 
16
struct GrapplingHookData
 
 
17
{
 
 
18
    int IsEmbedded;
 
 
19
    int IsEngaged;
 
 
20
    int Tightness;
 
 
21
 
 
 
22
    VECTORCH Position;
 
 
23
    MATRIXCH Orientation;
 
 
24
    int ShapeIndex;
 
 
25
    DISPLAYBLOCK *DispPtr;
 
 
26
}; 
 
 
27
 
 
 
28
static struct GrapplingHookData GrapplingHook;
 
 
29
 
 
 
30
void InitialiseGrapplingHook()
 
 
31
{
 
 
32
    GrapplingHook.IsEngaged = 0;
 
 
33
    GrapplingHook.IsEmbedded = 0;
 
 
34
    GrapplingHook.ShapeIndex = GetLoadedShapeMSL("spear");
 
 
35
    GrapplingHook.DispPtr = 0;
 
 
36
}
 
 
37
 
 
 
38
static DISPLAYBLOCK* CreateGrapplingHook()
 
 
39
{
 
 
40
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourGrapplingHook);
 
 
41
 
 
 
42
    if(!sbPtr)
 
 
43
        return NULL;
 
 
44
 
 
 
45
    DISPLAYBLOCK *dPtr = sbPtr->DisplayBlock = CreateActiveObject();
 
 
46
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_ROCKET);
 
 
47
    sbPtr->containingModule = ModuleFromPosition(&Global_VDB.VDB_World, NULL);
 
 
48
 
 
 
49
    if((NULL == dynPtr) || (NULL == dPtr) || (NULL == sbPtr->containingModule))
 
 
50
    {
 
 
51
        RemoveBehaviourStrategy(sbPtr);
 
 
52
        return NULL;
 
 
53
    }
 
 
54
 
 
 
55
    AssignNewSBName(sbPtr);
 
 
56
    dynPtr->PrevPosition = dynPtr->Position = Global_VDB.VDB_World;
 
 
57
 
 
 
58
    GrapplingHook.Orientation = Global_VDB.VDB_Mat;
 
 
59
    TransposeMatrixCH(&GrapplingHook.Orientation);
 
 
60
    dynPtr->OrientMat = GrapplingHook.Orientation;
 
 
61
 
 
 
62
    dynPtr->LinVelocity.vx = dynPtr->OrientMat.mat31;
 
 
63
    dynPtr->LinVelocity.vy = dynPtr->OrientMat.mat32;
 
 
64
    dynPtr->LinVelocity.vz = dynPtr->OrientMat.mat33;
 
 
65
 
 
 
66
    sbPtr->shapeIndex = GetLoadedShapeMSL("spear");
 
 
67
 
 
 
68
    dPtr->ObShape = sbPtr->shapeIndex;
 
 
69
    dPtr->ShapeData = mainshapelist[sbPtr->shapeIndex];
 
 
70
    dPtr->ObStrategyBlock = sbPtr;
 
 
71
    dPtr->ObWorld = dynPtr->Position;
 
 
72
    dPtr->ObEuler = dynPtr->OrientEuler;
 
 
73
    dPtr->ObMat = dynPtr->OrientMat;
 
 
74
 
 
 
75
    dPtr->extent.radius = 10;
 
 
76
 
 
 
77
    dPtr->extent.max_x = 10;
 
 
78
    dPtr->extent.max_y = 10;
 
 
79
    dPtr->extent.max_z = 10;
 
 
80
    dPtr->extent.min_x = -10;
 
 
81
    dPtr->extent.min_y = -10;
 
 
82
    dPtr->extent.min_z = -10;
 
 
83
 
 
 
84
    dPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
 
 
85
 
 
 
86
    return dPtr;
 
 
87
}
 
 
88
 
 
 
89
static void FireGrapplingHook()
 
 
90
{
 
 
91
    GrapplingHook.DispPtr = CreateGrapplingHook();
 
 
92
 
 
 
93
    if (GrapplingHook.DispPtr)
 
 
94
    {
 
 
95
        GrapplingHook.IsEngaged = 1;
 
 
96
        GrapplingHook.IsEmbedded = 0;
 
 
97
        GrapplingHook.Tightness = ONE_FIXED;
 
 
98
        Sound_Play(SID_GRAPPLE_THROW,"h");
 
 
99
    }
 
 
100
}
 
 
101
 
 
 
102
void DisengageGrapplingHook()
 
 
103
{
 
 
104
    GrapplingHook.IsEngaged = 0;
 
 
105
    GrapplingHook.IsEmbedded = 0;
 
 
106
 
 
 
107
    if (GrapplingHook.DispPtr)
 
 
108
    {
 
 
109
        RemoveBehaviourStrategy(GrapplingHook.DispPtr->ObStrategyBlock);
 
 
110
        GrapplingHook.DispPtr = NULL;
 
 
111
    }
 
 
112
}
 
 
113
 
 
 
114
void ActivateGrapplingHook()
 
 
115
{    
 
 
116
    GrapplingHook.IsEngaged ? DisengageGrapplingHook() : FireGrapplingHook();
 
 
117
}
 
 
118
 
 
 
119
void GrapplingHookBehaviour(STRATEGYBLOCK *sbPtr)
 
 
120
{
 
 
121
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
122
 
 
 
123
    if (!GrapplingHook.IsEmbedded)
 
 
124
    {
 
 
125
        COLLISIONREPORT *reportPtr = dynPtr->CollisionReportPtr;
 
 
126
 
 
 
127
        if(reportPtr)
 
 
128
        {
 
 
129
            char stickWhereYouAre = 0;
 
 
130
 
 
 
131
            if (reportPtr->ObstacleSBPtr)
 
 
132
            {
 
 
133
                DISPLAYBLOCK *dispPtr = reportPtr->ObstacleSBPtr->DisplayBlock;
 
 
134
 
 
 
135
                if (dispPtr && dispPtr->Module && !dispPtr->ObMorphCtrl)
 
 
136
                    stickWhereYouAre=1;
 
 
137
            }
 
 
138
            else
 
 
139
            {
 
 
140
                stickWhereYouAre = 1;
 
 
141
            }
 
 
142
 
 
 
143
            if(stickWhereYouAre)
 
 
144
            {
 
 
145
                dynPtr->IsStatic = 1;
 
 
146
                dynPtr->PrevPosition = dynPtr->Position;
 
 
147
                GrapplingHook.Position = dynPtr->Position;
 
 
148
                GrapplingHook.IsEmbedded = 1;
 
 
149
                Sound_Play(SID_GRAPPLE_HIT_WALL,"d",&dynPtr->Position);
 
 
150
            return;
 
 
151
            }
 
 
152
            else
 
 
153
            {
 
 
154
                DisengageGrapplingHook();
 
 
155
                return;
 
 
156
            }
 
 
157
        }
 
 
158
    }
 
 
159
    else
 
 
160
    {
 
 
161
        GrapplingHook.Tightness -= NormalFrameTime*4;
 
 
162
        if (GrapplingHook.Tightness < 0)
 
 
163
            GrapplingHook.Tightness = 0;
 
 
164
    }
 
 
165
}
 
 
166
 
 
 
167
void HandleGrapplingHookForces()
 
 
168
{
 
 
169
    if (GrapplingHook.IsEmbedded)
 
 
170
    {
 
 
171
        DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr;
 
 
172
        VECTORCH direction = GrapplingHook.Position;
 
 
173
        int distance;
 
 
174
 
 
 
175
        direction.vx -= dynPtr->Position.vx;
 
 
176
        direction.vy -= dynPtr->Position.vy-1000;
 
 
177
        direction.vz -= dynPtr->Position.vz;
 
 
178
 
 
 
179
        distance = Approximate3dMagnitude(&direction);
 
 
180
 
 
 
181
        if (distance > 4096 + 1024)
 
 
182
        {
 
 
183
            Normalise(&direction);
 
 
184
            dynPtr->LinImpulse.vx += MUL_FIXED(direction.vx,NormalFrameTime);
 
 
185
            dynPtr->LinImpulse.vy += MUL_FIXED(direction.vy,NormalFrameTime);
 
 
186
            dynPtr->LinImpulse.vz += MUL_FIXED(direction.vz,NormalFrameTime);
 
 
187
        }
 
 
188
        else if (distance > 1024)
 
 
189
        {
 
 
190
            int s = MUL_FIXED((distance-1024)*16,NormalFrameTime);
 
 
191
            Normalise(&direction);
 
 
192
            dynPtr->LinImpulse.vx += MUL_FIXED(direction.vx,s);
 
 
193
            dynPtr->LinImpulse.vy += MUL_FIXED(direction.vy,s);
 
 
194
            dynPtr->LinImpulse.vz += MUL_FIXED(direction.vz,s);
 
 
195
 
 
 
196
            dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->LinImpulse.vx,NormalFrameTime/2);
 
 
197
            dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->LinImpulse.vy,NormalFrameTime/2);
 
 
198
            dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->LinImpulse.vz,NormalFrameTime/2);
 
 
199
        }
 
 
200
 
 
 
201
        if (Approximate3dMagnitude(&dynPtr->LinImpulse) > ONE_FIXED)
 
 
202
        {
 
 
203
            Normalise(&dynPtr->LinImpulse);
 
 
204
        }
 
 
205
    }
 
 
206
}
 
 
207
 
 
 
208
void RenderGrapplingHook()
 
 
209
{
 
 
210
    if (GrapplingHook.IsEngaged && GrapplingHook.DispPtr)
 
 
211
    {
 
 
212
        VECTORCH cable[46];
 
 
213
        int i=1;
 
 
214
        {
 
 
215
            MATRIXCH mat = Global_VDB.VDB_Mat;
 
 
216
            TransposeMatrixCH(&mat);
 
 
217
 
 
 
218
            cable[0].vx = Global_VDB.VDB_World.vx-mat.mat31/128;
 
 
219
            cable[0].vy = Global_VDB.VDB_World.vy-mat.mat32/128+500;
 
 
220
            cable[0].vz = Global_VDB.VDB_World.vz-mat.mat33/128;
 
 
221
        }
 
 
222
 
 
 
223
        for (; i < 46; i++)
 
 
224
        {
 
 
225
            cable[i].vx = ((45-i)*cable[0].vx + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vx)/45;
 
 
226
            cable[i].vy = ((45-i)*cable[0].vy + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vy)/45;
 
 
227
            cable[i].vz = ((45-i)*cable[0].vz + (i)*GrapplingHook.DispPtr->ObStrategyBlock->DynPtr->Position.vz)/45;
 
 
228
 
 
 
229
            if (GrapplingHook.Tightness != 0)
 
 
230
            {
 
 
231
                int x = GetSin((302*i+CloakingPhase)&4095) / 256;
 
 
232
                int y = GetSin((502*i+200+CloakingPhase)&4095) / 256;
 
 
233
                int z = GetCos((302*i+100+CloakingPhase)&4095) / 256;
 
 
234
                int u = GetSin( ((4096*i)/45)&4095 );
 
 
235
                u = MUL_FIXED(MUL_FIXED(u,u),GrapplingHook.Tightness);
 
 
236
                cable[i].vx += MUL_FIXED(u,x);
 
 
237
                cable[i].vy += MUL_FIXED(u,y);
 
 
238
                cable[i].vz += MUL_FIXED(u,z);
 
 
239
            }
 
 
240
        }
 
 
241
 
 
 
242
        {
 
 
243
            MATRIXCH mat;
 
 
244
            VECTORCH dir = cable[45];
 
 
245
            dir.vx -= cable[0].vx;
 
 
246
            dir.vy -= cable[0].vy;
 
 
247
            dir.vz -= cable[0].vz;
 
 
248
            Normalise(&dir);
 
 
249
            MakeMatrixFromDirection(&dir,&mat);
 
 
250
            DrawCable(cable, &mat);
 
 
251
        }
 
 
252
    }
 
 
253
}
 
 
254
 
 
 
255
/*--------------------**
 
 
256
** Loading and Saving **
 
 
257
**--------------------*/
 
 
258
#include "savegame.h"
 
 
259
 
 
 
260
typedef struct grapple_save_block
 
 
261
{
 
 
262
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
263
 
 
 
264
    int IsEmbedded;
 
 
265
    int IsEngaged;
 
 
266
    int Tightness;
 
 
267
 
 
 
268
    VECTORCH Position;
 
 
269
    MATRIXCH Orientation;
 
 
270
//strategy block stuff
 
 
271
    DYNAMICSBLOCK dynamics;
 
 
272
} GRAPPLE_SAVE_BLOCK;
 
 
273
 
 
 
274
#define SAVELOAD_BLOCK block
 
 
275
#define SAVELOAD_BEHAV (&GrapplingHook)
 
 
276
 
 
 
277
void LoadStrategy_Grapple(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
278
{
 
 
279
    GRAPPLE_SAVE_BLOCK* block = (GRAPPLE_SAVE_BLOCK*) header;
 
 
280
 
 
 
281
    //check the size of the save block
 
 
282
    if(header->size != sizeof(*block))
 
 
283
        return;
 
 
284
 
 
 
285
    //create the grappling hook
 
 
286
    GrapplingHook.DispPtr = CreateGrapplingHook();
 
 
287
    if(!GrapplingHook.DispPtr)
 
 
288
        return;
 
 
289
 
 
 
290
    //copy suff from the save block
 
 
291
    COPYELEMENT_LOAD(IsEmbedded)
 
 
292
    COPYELEMENT_LOAD(IsEngaged)
 
 
293
    COPYELEMENT_LOAD(Tightness)
 
 
294
    COPYELEMENT_LOAD(Position)
 
 
295
    COPYELEMENT_LOAD(Orientation)
 
 
296
 
 
 
297
    *GrapplingHook.DispPtr->ObStrategyBlock->DynPtr = block->dynamics;
 
 
298
}
 
 
299
 
 
 
300
void SaveStrategy_Grapple(STRATEGYBLOCK* sbPtr)
 
 
301
{
 
 
302
    GRAPPLE_SAVE_BLOCK* block;
 
 
303
 
 
 
304
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
305
 
 
 
306
    //copy stuff to the save block
 
 
307
    COPYELEMENT_SAVE(IsEmbedded)
 
 
308
    COPYELEMENT_SAVE(IsEngaged)
 
 
309
    COPYELEMENT_SAVE(Tightness)
 
 
310
    COPYELEMENT_SAVE(Position)
 
 
311
    COPYELEMENT_SAVE(Orientation)
 
 
312
 
 
 
313
    block->dynamics = *sbPtr->DynPtr;
 
 
314
    block->dynamics.CollisionReportPtr=0;
 
 
315
}