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