| | 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 | } |