Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Log started
- Project X! Version : 0.8.0.3104
- for WA 3.6.31.0
- WormKit Module
- Unlocked code region
- Unlocked data region
- Loading from : px3d.dll
- PX3D library loaded and binded
- Cleaning old render
- Cleaning old render VFT
- Precision : Double
- Round Mode : Nearest
- Making Multi Player form scheme select..
- Done
- Begin hosting
- Done
- Making Multi Player form scheme select resources..
- Result MWAB : 3476002
- Done
- Loading level dat file : data\current.thm 0x0043BC6E
- Constructor of Multi Player Match form..
- Scheme list saved
- Checking saved PX Scheme
- Loading scheme PX Normal.pxs
- Loading scheme file PXSchemes\PX Normal.pxs
- SchemeMan is being initializated..
- PXS : Loading pxdata.pxd
- PXS : Symbols loaded and linked
- PXFS has been initialized
- Processing scheme scripts.
- PXS : Making scheme scripts
- PXS : Library Code :
- //This unit allows to detect
- //weapon which missile belongs to
- CWeapon* u_lweap;
- int DistBetweenObjs(CGObject* ObA, CGObject* ObB)
- {
- int dx = ObA->PosX - ObB->PosX;
- int dy = ObA->PosY - ObB->PosY;
- int r = sqrt(dx * dx + dy * dy);
- return r;
- };
- void MissileIndex::InitGraphic()
- {
- u_lweap = NullObj;
- };
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- u_lweap = Weap;
- super;
- u_lweap = NullObj;
- };
- override CMissile::CMissile(CObject* parent, CWeaponLaunch* ldata, CShootDesc* sdata)
- {
- weap = u_lweap;
- super;
- };
- override void CTurnGame::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if (Type == M_TURNBEGIN)
- {
- for (local i = 1; i < Env->Objs.Count; i++)
- {
- local mine = CMine(Env->Objs.Objs[i]);
- if (mine is CMine)
- {
- if (mine->autoTurnDestruct)
- {
- mine->Explosion();
- mine->Free(true);
- i--;
- }
- }
- }
- }
- super;
- }
- override CMine::CMine(CObject* Parent,CMineParams* Params,CShootDesc* SDesc,bool Snap,int Unk)
- {
- autoTurnDestruct = false;
- autoDestroyTimer = -1;
- super;
- }
- override void CMine::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if (Type == M_FRAME)
- {
- if (autoDestroyTimer > 0)
- {
- autoDestroyTimer--;
- } else if (autoDestroyTimer == 0) {
- Explosion();
- Free(true);
- return;
- }
- }
- super;
- }
- PXS : Library Code :
- float srandom_p()
- {
- int n = GS->GetRandom() % 10000;
- res = n / 10000.0;
- return res;
- };
- float srandom_b()
- {
- int n = GS->GetRandom() % 10000;
- res = n / 5000.0 - 1.0;
- return res;
- };
- int RandomInt(int min, int max)
- {
- return (GS->GetRandom()%(max - min + 1)) + min;
- }
- float RandomFloat(float min, float max)
- {
- int n = (GS->GetRandom()%10000);
- float s = min + ((max - min) * n) / 10000.0;
- return s;
- }
- PXS : Library Code :
- void SetTeamWon(int team)
- {
- local w = GetCurrentWorm();
- if (w != NullObj && GetTeamColor(w->WormTeam) != GetTeamColor(team))
- {
- Root->DoExplosion(w->PosX, w->PosY, 100, 8, 1, 0);
- }
- if (#RESPAWN_CONTROL)
- {
- if (rControl->enabled)
- {
- rControl->SetWinner(GetTeamColor(team));
- return;
- }
- }
- for (local i = 1; i <= 6; i++)
- {
- if (team == i) continue;
- for (local worm = 1; worm <= 8; worm++)
- {
- GS->Info.SetWormHealth(i, worm, 0);
- }
- }
- }
- bool IsTeamAlive(int team)
- {
- if (Root->GetObject(TI_Team, team) == NullObj) return false;
- for (local i = 1; i <= 8; i++)
- {
- if (GS->Info.Teams[team-1].Worms[i-1].Health > 0) return true;
- }
- return false;
- }
- CWorm* GetCurrentWorm()
- {
- local CurWorm = Root->CurWorm;
- local CurTeam = Root->CurTeam;
- if (CurWorm <= 0 || CurWorm > 8) return NullObj;
- if (CurTeam <= 0 || CurTeam > 6) return NullObj;
- return Root->GetObject(2, CurWorm + 16 * CurTeam);
- };
- int GetWormColor(CWorm* worm)
- {
- return GetTeamColor(worm->WormTeam) + 1;
- };
- bool CGObject::IsInBox(fixed left, fixed top, fixed right, fixed bottom)
- {
- if (PosX > left && PosX < right)
- {
- if (PosY > top && PosY < bottom)
- {
- return true;
- }
- }
- return false;
- }
- bool CGObject::IsValid()
- {
- if ((this is CGObject) == false) return false;
- for (local i = 1; i < Env->Objs.Count; i+= 1)
- {
- if (Env->Objs.Objs[i] == this)
- {
- return true;
- }
- }
- return false;
- }
- int GetFreeWormIndex(int Team)
- {
- TNW = GS->Info.Teams[Team-1].NWorms;
- for (i = 1; i <= TNW; i+=1)
- {
- if (GS->Info.Teams[Team-1].Worms[i-1].State == 135) return i;
- };
- if (TNW < 8)
- {
- return TNW + 1;
- };
- return -1;
- };
- void ExpandNWorms(int Team, int ExpTo)
- {
- local LIndex = GS->Info.Teams[Team-1].NWorms;
- GS->Info.Teams[Team-1].NWorms = ExpTo;
- for (i = LIndex + 1; i < ExpTo; i+=1)
- {
- GS->Info.Teams[Team-1].Worms[i-1].State = 135; //DEAD NAU
- };
- GS->Info.Teams[Team-1].Worms[ExpTo].State = 100;
- };
- CWorm* RessurectWorm(int Index, int Team, fixed x, fixed y)
- {
- return RessurectWormEx(Index, Team, x, y, "New Worm", 100);
- }
- CWorm* RessurectWormEx(int Index, int Team, fixed x, fixed y, string wName, int Health)
- {
- T = Root->GetObject(TI_Team, Team);
- if (T == NullObj)
- {
- return T;
- };
- CWormParams wParam;
- zero(&wParam);
- wParam.SetName(wName);
- wParam.SetPosition(Health, x, y, true);
- GS->Info.Teams[Team-1].Worms[Index-1].Health = Health;
- worm = new CWorm(T, Team, Index, &wParam);
- GS->Info.Teams[Team-1].Worms[Index-1].Health = Health;
- if (Index > GS->Info.Teams[Team-1].NWorms)
- {
- ExpandNWorms(Team, Index);
- };
- return worm;
- };
- PXS : Library Code :
- float Lerp(float delta, float from, float to) {
- if (delta > 1) return to;
- if (delta < 0) return from;
- return from + (to - from) * delta;
- }
- float NormalizeAngle(float a)
- {
- while(a > 3.141593) a -= 6.283186;
- while(a <= -3.141593) a += 6.283186;
- return a;
- }
- float LerpAngle(float c, float a, float b)
- {
- a = NormalizeAngle(a);
- b = a + NormalizeAngle(b - a);
- return NormalizeAngle(Lerp(c, a, b));
- }
- int Sign(float n)
- {
- if(n<0) return -1;
- else if(n>0) return 1;
- return 0;
- }
- // t - time to shoot
- // d - delta
- // g - gravity or wind
- float SolveBallistic(float d, float t, float g)
- {
- local a = (2 * d - g * t * t) / (2 * t);
- return a;
- };
- PXS : Library Code :
- CKeySync* keySync;
- void sync_script::Init()
- {
- keySync = new CKeySync(RegisterPXMessage());
- };
- override void CTurnGame::SetCurrentTeam(int Team)
- {
- super;
- for (local i = 0; i < 256; i+=1)
- {
- keySync->kRStates[i] = false;
- }
- }
- CKeySync::CKeySync(int MType)
- {
- msgType = MType;
- kSync = new bool[256];
- kStates = new bool[256];
- kRStates = new bool[256];
- kPStates = new bool[256];
- for (local i = 0; i < 256; i+=1)
- {
- kSync[i] = false;
- kStates[i] = false;
- kRStates[i] = false;
- kPStates[i] = false;
- };
- };
- //adds key for syncronization
- void CKeySync::AddKey(int kIndex)
- {
- if (kIndex >= 0 && kIndex < 256) kSync[kIndex] = true;
- };
- //is key still pressed
- bool CKeySync::KeyPressed(int kIndex)
- {
- return kRStates[kIndex];
- };
- //is key JUST pressed
- bool CKeySync::KeyPressedNow(int kIndex)
- {
- return kPStates[kIndex];
- };
- void CKeySync::ProcessInput()
- {
- for (local i = 0; i < 256; i++)
- {
- if (kSync[i] == false) continue;
- local kpr = IsKeyPressed(i);
- if (kpr != kStates[i])
- {
- if (kpr)
- {
- GG->queue2->AddPXMessage( msgType, i, 1);
- } else {
- GG->queue2->AddPXMessage( msgType, i, 0);
- }
- kStates[i] = kpr;
- }
- }
- }
- void CKeySync::OnMessage(CMessageData* MData)
- {
- if (MData->GetParameter(0) == msgType)
- {
- local ki = MData->GetParameter(1);
- local kp = MData->GetParameter(2);
- if (kp)
- {
- if (kRStates[ki] == false) kPStates[ki] = true;
- kRStates[ki] = true;
- } else {
- kRStates[ki] = false;
- }
- }
- }
- void CKeySync::OnFrame()
- {
- for (local i = 0; i < 256; i++)
- {
- kPStates[i] = false;
- }
- }
- override void CTurnGame::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if (Type == M_INPUT)
- {
- keySync->ProcessInput();
- }
- if (Type == M_PXMESSAGE)
- {
- keySync->OnMessage(MData);
- }
- super;
- if (Type == M_FRAME)
- {
- keySync->OnFrame();
- }
- };
- PXS : Library Code : CGObject* Trace(CObject* parent, CColMask* colmask, fixed x, fixed y, float ang, float res, int maxlen, int flags, int* outL)
- {
- tx = float(x);
- ty = float(y);
- dx = sin(ang) * res;
- dy = 0 - cos(ang) * res; //lol, TODO
- nchecks = int(maxlen / res);
- for (i = 0; i < nchecks; i += 1)
- {
- obj = CheckMaskAt(parent, colmask, tx, ty, flags);
- if (obj != NullObj)
- {
- *outL = i * res;
- return obj;
- };
- tx += dx;
- ty += dy;
- };
- *outL = maxlen;
- return NullObj;
- };
- CGObject* DTrace(CObject* parent, CColMask* colmask, fixed x, fixed y, fixed shx, fixed shy, int nchecks, int flags, int* outInter)
- {
- tx = float(x);
- ty = float(y);
- dx = float(shx);
- dy = float(shy); //lol, TODO
- for (i = 0; i < nchecks; i += 1)
- {
- obj = CheckMaskAt(parent, colmask, tx, ty, flags);
- if (obj != NullObj)
- {
- *outInter = i;
- return obj;
- };
- tx += dx;
- ty += dy;
- };
- *outInter = nchecks;
- return NullObj;
- };
- CGObject* BTrace(CObject* parent, CColMask* colmask, fixed x, fixed y, float shx, float shy, fixed g, int nchecks, int flags, int* outInter)
- {
- tx = float(x);
- ty = float(y);
- dx = shx;
- dy = shy; //lol, TODO
- ddy = float(g);
- for (i = 0; i < nchecks; i += 1)
- {
- obj = CheckMaskAt(parent, colmask, tx, ty, flags);
- if (obj != NullObj)
- {
- // parent->DoExplosion( 1, tx, ty, 100, 10, 0, 1);
- *outInter = i;
- return obj;
- };
- tx += dx;
- ty += dy;
- dy += ddy;
- };
- *outInter = nchecks;
- return NullObj;
- };
- CColMask *MASK_PIXEL;
- void tracers::InitGraphic()
- {
- CBitmap1 *bmp = new CBitmap1(1, 1);
- bmp->SetPixel(0, 0, 1);
- MASK_PIXEL = new CColMask(1,1,bmp);
- }
- CTraceRes::CTraceRes()
- {
- HitX = 0;
- HitY = 0;
- PreHitX = 0;
- PreHitY = 0;
- TangentX = 0.0;
- TangentY = 0.0;
- NormalX = 0.0;
- NormalY = 0.0;
- StartsSolid = false;
- LeftSolidX = 0;
- LeftSolidY = 0;
- HitObject = NullObj;
- Hit = false;
- Point1X = 0;
- Point1Y = 0;
- Point2X = 0;
- Point2Y = 0;
- }
- bool MatchCollisionGroup(CGObject *obj, int flags)
- {
- if(obj->ClType == OC_Landscape) { if(flags & 2 == 0) return false; } // Land
- else if(obj->ClType == OC_Worm)
- {
- if(flags & 4 == 0) // Standing worms
- {
- if(obj->ObjState == WS_IDLE) return false;
- if(obj->ObjState == WS_WALKING) return false;
- if(obj->ObjState == WS_AIMING) return false;
- if(obj->ObjState == WS_SETPOWER) return false;
- if(obj->ObjState == WS_JUMPPREPARE) return false;
- }
- if(flags & 8 == 0) // Worms with weapon
- {
- if(obj->ObjState == WS_FIRED) return false;
- if(obj->ObjState == WS_FIRECONT) return false;
- if(obj->ObjState == WS_DRILLING) return false;
- if(obj->ObjState == WS_TELEPORTING) return false;
- if(obj->ObjState == WS_CONTROL_WEAPON) return false;
- if(obj->ObjState == WS_BLOWTORCH) return false;
- }
- if(flags & 16 == 0) // Worms in mid-air
- {
- if(obj->ObjState == WS_POING) return false;
- if(obj->ObjState == WS_JUMP) return false;
- if(obj->ObjState == WS_PARACHUTE) return false;
- if(obj->ObjState == WS_SLIDING) return false;
- if(obj->ObjState == WS_POWERFLY) return false;
- if(obj->ObjState == WS_FLYING) return false;
- if(obj->ObjState == WS_FLYING2) return false;
- if(obj->ObjState == WS_JETPACK) return false;
- if(obj->ObjState == WS_AFTERROPE) return false;
- }
- if(flags & 32 == 0) // Worms on rope/bungee
- {
- if(obj->ObjState == WS_ROPING) return false;
- if(obj->ObjState == WS_BUNGEE) return false;
- }
- if(flags & 64 == 0) // Frozen worms
- {
- if(obj->ObjState == WS_FROZEN) return false;
- }
- if(flags & 256 == 0) // Suicide bomber/kamikaze
- {
- if(obj->ObjState == WS_FIREPUNCH) return false;
- if(obj->ObjState == WS_SUICIDEBOMBER) return false;
- }
- }
- else if(obj->ClType == OC_Mine) { if(flags & 1024 == 0) return false; } // Mines
- else if(obj->ClType == OC_Crate) { if(flags & 2048 == 0) return false; } // Crates
- else if(obj->ClType == OC_Cross) { if(flags & 8192 == 0) return false; } // Gravestones
- else if(obj->ClType == OC_Missile) { if(flags & 32768 == 0) return false; } // Weapons
- else if(obj->ClType == OC_Arrow) { if(flags & 65536 == 0) return false; } // Arrows
- else if(obj->ClType == OC_OilDrum) { if(flags & 131072 == 0) return false; } // Oil drums
- else { if(flags & (1 << obj->Layer) == 0) return false; } // Custom objects
- return true;
- }
- CGObject* FindInMask(CGObject* parent, CColMask* msk, int x, int y, int flags)
- {
- int i;
- CGObject *obj;
- if(flags <= 0 && parent != NullObj) flags = parent->ColGroup;
- for(i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == parent) continue;
- if(obj == NullObj) continue;
- if(MatchCollisionGroup(obj, flags) == false) continue;
- if(msk->Check(x, y, obj->ColMask, obj->PosX, obj->PosY))
- {
- return obj;
- }
- }
- return NullObj;
- }
- CGObject *_TraceMask(CObject *parent, CColMask *mask, int x1, int y1, int x2, int y2, int flags, int *xr, int *yr, int *xl, int *yl, int *ssolid, int *xls, int *yls)
- {
- int dx;
- int dy;
- int abs_dx;
- int abs_dy;
- int sx;
- int sy;
- int dir;
- int e;
- bool first = true;
- bool insolid = false;
- CGObject *obj;
- dx = x2 - x1;
- dy = y2 - y1;
- if(dx == 0) { sx = 0; abs_dx = 0; }
- else if(dx > 0) { sx = 1; abs_dx = dx; }
- else { sx = 0-1; abs_dx = 0-dx; }
- if(dy == 0) { sy = 0; abs_dy = 0; }
- else if(dy > 0) { sy = 1; abs_dy = dy; }
- else { sy = 0-1; abs_dy = 0-dy; }
- if(abs_dx >= abs_dy) { e = abs_dx; dir = 0; }
- else { e = abs_dy; dir = 1; }
- abs_dx = abs_dx * 2;
- abs_dy = abs_dy * 2;
- *xl = x1;
- *yl = y1;
- *xls = x1;
- *yls = y1;
- *ssolid = 0;
- while(true)
- {
- obj = FindInMask(parent, mask, x1, y1, flags);
- if(obj != NullObj)
- {
- if(first)
- {
- *ssolid = 1;
- insolid = true;
- }
- else
- {
- if(insolid == false)
- {
- *xr = x1; *yr = y1;
- return obj;
- }
- }
- }
- else
- {
- if(insolid)
- {
- insolid = false;
- *xls = x1;
- *yls = y1;
- }
- }
- *xl = x1;
- *yl = y1;
- if(dir == 0)
- {
- x1 += sx;
- if(x1 == x2) break;
- if(sy != 0)
- {
- e -= abs_dy;
- if(e < 0)
- {
- y1 += sy;
- e += abs_dx;
- }
- }
- }
- else
- {
- y1 += sy;
- if(y1 == y2) break;
- if(sx != 0)
- {
- e -= abs_dx;
- if(e <= 0)
- {
- x1 += sx;
- e += abs_dy;
- }
- }
- }
- first = false;
- }
- *xr = x2;
- *yr = y2;
- return NullObj;
- }
- CGObject *TraceMask(CObject *parent, CColMask *mask, int x1, int y1, int x2, int y2, int flags, int *xr, int *yr)
- {
- int t;
- return _TraceMask(parent, mask, x1, y1, x2, y2, flags, xr, yr, &t, &t, &t, &t, &t);
- }
- CGObject *TraceLine(CObject *parent, int x1, int y1, int x2, int y2, int flags, int *xr, int *yr)
- {
- return TraceMask(parent, MASK_PIXEL, x1, y1, x2, y2, flags, xr, yr);
- }
- bool TraceMaskEx(CObject *parent, CColMask *mask, int x1, int y1, int x2, int y2, int flags, CTraceRes *res)
- {
- int num_points = 6;
- int x;
- int y;
- int xl;
- int yl;
- int ss;
- int xls;
- int yls;
- CGObject *obj = _TraceMask(parent, mask, x1, y1, x2, y2, flags, &x, &y, &xl, &yl, &ss, &xls, &yls);
- CGObject *o;
- res->HitX = x;
- res->HitY = y;
- res->HitObject = obj;
- if(ss == 1) res->StartsSolid = true;
- else res->StartsSolid = false;
- res->PreHitX = xl;
- res->PreHitY = yl;
- res->LeftSolidX = xls;
- res->LeftSolidY = yls;
- if(obj == NullObj)
- {
- res->TangentX = 1.0;
- res->TangentY = 0.0;
- res->NormalX = 0.0;
- res->NormalY = -1.0;
- res->Point1X = 0;
- res->Point1Y = 0;
- res->Point2X = 0;
- res->Point2Y = 0;
- res->Hit = false;
- return false;
- }
- int cx0;
- int cy0;
- int cx1 = x;
- int cy1 = y;
- int cx2 = x;
- int cy2 = y;
- int dx;
- int dy;
- int t;
- int abs_dx;
- int abs_dy;
- int rx;
- int ry;
- float tangx;
- float tangy;
- float normx;
- float normy;
- float dist;
- bool changed;
- dx = x2 - x1;
- dy = y2 - y1;
- if(dx == 0) { rx = 0; abs_dx = 0; }
- else if(dx > 0) { rx = 1; abs_dx = dx; }
- else { rx = 0-1; abs_dx = 0-dx; }
- if(dy == 0) { ry = 0; abs_dy = 0; }
- else if(dy > 0) { ry = 1; abs_dy = dy; }
- else { ry = 0-1; abs_dy = 0-dy; }
- int n;
- n = num_points;
- dx = rx;
- dy = 0;
- changed = false;
- while(true)
- {
- o = FindInMask(parent, mask, cx1, cy1, flags);
- if(o != NullObj)
- {
- n -= 1;
- t = dx;
- dx = dy;
- dy = 0-t;
- if(n<=0) break;
- }
- else
- {
- t = dx;
- dx = 0-dy;
- dy = t;
- }
- cx1 += dx;
- cy1 += dy;
- if(cx1==x)
- {
- if(cy1==y)
- {
- if(changed)
- {
- break;
- }
- else
- {
- dx = 0;
- dy = ry;
- changed = true;
- }
- }
- }
- }
- n = num_points;
- dx = rx;
- dy = 0;
- changed = false;
- while(true)
- {
- o = FindInMask(parent, mask, cx2, cy2, flags);
- if(o != NullObj)
- {
- n -= 1;
- t = dx;
- dx = 0-dy;
- dy = t;
- if(n<=0) break;
- }
- else
- {
- t = dx;
- dx = dy;
- dy = 0-t;
- }
- cx2 += dx;
- cy2 += dy;
- if(cx2==x)
- {
- if(cy2==y)
- {
- if(changed)
- {
- break;
- }
- else
- {
- dx = 0;
- dy = ry;
- changed = true;
- }
- }
- }
- }
- res->Point1X = cx1;
- res->Point1Y = cy1;
- res->Point2X = cx2;
- res->Point2Y = cy2;
- tangx = (cx2 - cx1);
- tangy = (cy2 - cy1);
- normx = (cy1 - cy2);
- normy = (cx2 - cx1);
- dist = sqrt(normx*normx + normy*normy);
- if(dist > 0)
- {
- res->TangentX = tangx / dist;
- res->TangentY = tangy / dist;
- res->NormalX = normx / dist;
- res->NormalY = normy / dist;
- }
- else
- {
- res->TangentX = 1.0;
- res->TangentY = 0.0;
- res->NormalX = 0.0;
- res->NormalY = -1.0;
- }
- res->Hit = true;
- return true;
- }
- CGObject *TraceLineEx(CObject *parent, int x1, int y1, int x2, int y2, int flags, CTraceRes *res)
- {
- TraceMaskEx(parent, MASK_PIXEL, x1, y1, x2, y2, flags, res);
- return res->HitObject;
- }
- PXS : Library Code :
- bool GameStartedToDestroy; //true when game is ending
- int g_tColorInd[6];
- int g_tColorInd2[7]; //reversed
- //rad is actually about 1/2 of actual diameter :D
- bool TeleportObject(CGObject* obj, int tX, int tY, int rad, bool onGround, int flags)
- {
- local dx = 0;
- local dy = -1;
- local iX = obj->PosX; local iY = obj->PosY;
- obj->PosY = -1000;
- l = 1;
- for (local nm = 0; nm <= rad; nm++)
- {
- for (local i = 0; i < l; i++)
- {
- obj->PosY -= 1;
- if (Env->CheckCollisionEx(obj, tX, tY, obj->ColMask, flags) == NullObj)
- {
- obj->PosY -= 1;
- if (!onGround || (Env->CheckCollisionEx( obj, tX, tY + 1, obj->ColMask, flags) != NullObj))
- {
- obj->PosX = tX;
- obj->PosY = tY;
- return true;
- }
- }
- tX += dx;
- tY += dy;
- }
- local t = dx;
- dx = -dy;
- dy = t;
- if (nm % 2 == 1)
- {
- l++;
- }
- }
- obj->PosY = iY;
- return false;
- }
- string MakeZeroedNumber(int n, int minLen)
- {
- string str = ItoA(n);
- while (StrLen(str) < minLen) str = StrCon("0", str);
- return str;
- }
- void generateTColorInd()
- {
- tExists = new bool[7];
- sTeam = 1;
- for (i = 0; i < 7; i++)
- {
- tExists[i] = false;
- g_tColorInd2[i] = -1;
- }
- for (i = 1; i <= 6; i++)
- {
- if (Root->GetObject(TI_Team, i) != NullObj)
- {
- tExists[GetTeamColor(i)] = true;
- }
- }
- for (i = 0; i <= 5; i++)
- {
- if (tExists[i])
- {
- g_tColorInd2[sTeam] = i;
- g_tColorInd[i] = sTeam++;
- }
- }
- }
- override void CTurnGame::Free(bool FreeMem)
- {
- GameStartedToDestroy = true;
- super;
- GameStartedToDestroy = false;
- }
- CBitmap1* MakeCircleMask(int rad)
- {
- msk = new CBitmap1(rad * 2, rad * 2);
- rsq = rad * rad;
- drad = rad * 2;
- // hrad = rad / 2;
- for (int i = 0; i < drad; i+=1)
- {
- cwidth = int(sqrt(rsq - (i - rad) * (i - rad)));
- lborder = rad - cwidth;
- rborder = rad + cwidth;
- if (rborder >= drad) rborder = drad - 1;
- msk->HLine(lborder, rborder, i, 1);
- };
- return msk;
- };
- CBitmap1* MakeRectMask(int sx, int sy)
- {
- msk = new CBitmap1(sx, sy);
- msk->Rect( 0, 0, sx, sy, 1);
- return msk;
- }
- CBitmap1* MakePixelMask()
- {
- msk = new CBitmap1(1, 1);
- msk->SetPixel(0, 0, 1);
- return msk;
- };
- CGObject* CheckMaskAt(CGObject* Obj, CColMask* msk, fixed x, fixed y, int flags)
- {
- nObj = Env->Objs.Count;
- for (i = 0; i < nObj; i += 1)
- {
- trg = CGObject(Env->Objs.Objs[i]);
- if (trg == Obj) continue;
- if (trg == NullObj) continue;
- if (flags >= 0 && flags != trg->Layer) continue;
- if (msk->Check(x, y, trg->ColMask, trg->PosX, trg->PosY))
- {
- return trg;
- };
- };
- return NullObj;
- };
- void GetTeamColorRGB(int clr, int* r, int* g, int* b)
- {
- if (clr == 1)
- {
- *r = 255;
- *g = 128;
- *b = 128;
- } else if (clr == 2)
- {
- *r = 0;
- *g = 150;
- *b = 255;
- } else if (clr == 3)
- {
- *r = 0;
- *g = 208;
- *b = 0;
- } else if (clr == 4)
- {
- *r = 255;
- *g = 255;
- *b = 64;
- } else if (clr == 5)
- {
- *r = 232;
- *g = 0;
- *b = 232;
- } else if (clr == 6)
- {
- *r = 80;
- *g = 255;
- *b = 255;
- } else {
- *r = 255;
- *g = 255;
- *b = 255;
- }
- }
- int GetTeamColorRGB(int clr)
- {
- int r;
- int g;
- int b;
- GetTeamColorRGB(clr, &r, &g, &b);
- return RGB(r, g, b);
- }
- PXS : Library Code :
- // Math constants
- float MATH_TWO_PI;
- float MATH_PI;
- float MATH_HALF_PI;
- float MATH_QUARTER_PI;
- // Layer enums
- int LAYER_UNUSED0 ;
- int LAYER_TERRAIN ;
- int LAYER_WORM_ON_TERRAIN ;
- int LAYER_WORM_USING_WEAPON ;
- int LAYER_WORM_IN_MIDAIR ;
- int LAYER_WORM_ON_ROPE ;
- int LAYER_WORM_FROZEN ;
- int LAYER_UNUSED7 ;
- int LAYER_KAMIKAZE ;
- int LAYER_GASCANISTER ;
- int LAYER_MINE ;
- int LAYER_CRATE ;
- int LAYER_DONORCARD ;
- int LAYER_GRAVESTONE ;
- int LAYER_UNUSED14 ;
- int LAYER_OTHERWEAPON ;
- int LAYER_ARROW ;
- int LAYER_OILDRUM ;
- int LAYER_UNUSED18 ;
- int LAYER_UNUSED19 ;
- int LAYER_UNUSED20 ;
- int LAYER_UNUSED21 ;
- int LAYER_SKIMMING ;
- int LAYER_UNUSED23 ;
- int LAYER_UNUSED24 ;
- int LAYER_UNUSED25 ;
- int LAYER_UNUSED26 ;
- int LAYER_UNUSED27 ;
- int LAYER_UNUSED28 ;
- int LAYER_UNUSED29 ;
- int LAYER_UNUSED30 ;
- // Collision "group" enums (more like collision mask)
- int CMASK_UNUSED0 ;
- int CMASK_TERRAIN ;
- int CMASK_WORM_ON_TERRAIN ;
- int CMASK_WORM_USING_WEAPON ;
- int CMASK_WORM_IN_MIDAIR ;
- int CMASK_WORM_ON_ROPE ;
- int CMASK_WORM_FROZEN ;
- int CMASK_UNUSED7 ;
- int CMASK_KAMIKAZE ;
- int CMASK_GASCANISTER ;
- int CMASK_MINE ;
- int CMASK_CRATE ;
- int CMASK_DONORCARD ;
- int CMASK_GRAVESTONE ;
- int CMASK_UNUSED14 ;
- int CMASK_OTHERWEAPON ;
- int CMASK_ARROW ;
- int CMASK_OILDRUM ;
- int CMASK_UNUSED18 ;
- int CMASK_UNUSED19 ;
- int CMASK_UNUSED20 ;
- int CMASK_UNUSED21 ;
- int CMASK_SKIMMING ;
- int CMASK_UNUSED23 ;
- int CMASK_UNUSED24 ;
- int CMASK_UNUSED25 ;
- int CMASK_UNUSED26 ;
- int CMASK_UNUSED27 ;
- int CMASK_UNUSED28 ;
- int CMASK_UNUSED29 ;
- int CMASK_UNUSED30 ;
- // Preset CMASK enums
- int CMASK_DEFAULT_COLLIDEABLE;
- void px_enums::FirstFrame()
- {
- MATH_TWO_PI = 6.283186;
- MATH_PI = 3.141593;
- MATH_HALF_PI = 1.570796;
- MATH_QUARTER_PI = 0.785398;
- LAYER_UNUSED0 = 0;
- LAYER_TERRAIN = 1;
- LAYER_WORM_ON_TERRAIN = 2;
- LAYER_WORM_USING_WEAPON = 3;
- LAYER_WORM_IN_MIDAIR = 4;
- LAYER_WORM_ON_ROPE = 5;
- LAYER_WORM_FROZEN = 6;
- LAYER_UNUSED7 = 7;
- LAYER_KAMIKAZE = 8;
- LAYER_GASCANISTER = 9;
- LAYER_MINE = 10;
- LAYER_CRATE = 11;
- LAYER_DONORCARD = 12;
- LAYER_GRAVESTONE = 13;
- LAYER_UNUSED14 = 14;
- LAYER_OTHERWEAPON = 15;
- LAYER_ARROW = 16;
- LAYER_OILDRUM = 17;
- LAYER_UNUSED18 = 18;
- LAYER_UNUSED19 = 19;
- LAYER_UNUSED20 = 20;
- LAYER_UNUSED21 = 21;
- LAYER_SKIMMING = 22;
- LAYER_UNUSED23 = 23;
- LAYER_UNUSED24 = 24;
- LAYER_UNUSED25 = 25;
- LAYER_UNUSED26 = 26;
- LAYER_UNUSED27 = 27;
- LAYER_UNUSED28 = 28;
- LAYER_UNUSED29 = 29;
- LAYER_UNUSED30 = 30;
- CMASK_UNUSED0 = 1;
- CMASK_TERRAIN = 2;
- CMASK_WORM_ON_TERRAIN = 4;
- CMASK_WORM_USING_WEAPON = 8;
- CMASK_WORM_IN_MIDAIR = 16;
- CMASK_WORM_ON_ROPE = 32;
- CMASK_WORM_FROZEN = 64;
- CMASK_UNUSED7 = 128;
- CMASK_KAMIKAZE = 256;
- CMASK_GASCANISTER = 512;
- CMASK_MINE = 1024;
- CMASK_CRATE = 2048;
- CMASK_DONORCARD = 4096;
- CMASK_GRAVESTONE = 8192;
- CMASK_UNUSED14 = 16384;
- CMASK_OTHERWEAPON = 32768;
- CMASK_ARROW = 65536;
- CMASK_OILDRUM = 131072;
- CMASK_UNUSED18 = 262144;
- CMASK_UNUSED19 = 524288;
- CMASK_UNUSED20 = 1048576;
- CMASK_UNUSED21 = 2097152;
- CMASK_SKIMMING = 4194304;
- CMASK_UNUSED23 = 8388608;
- CMASK_UNUSED24 = 16777216;
- CMASK_UNUSED25 = 33554432;
- CMASK_UNUSED26 = 67108864;
- CMASK_UNUSED27 = 134217728;
- CMASK_UNUSED28 = 268435456;
- CMASK_UNUSED29 = 536870912;
- CMASK_UNUSED30 = 1073741824;
- CMASK_DEFAULT_COLLIDEABLE = CMASK_TERRAIN
- | CMASK_WORM_ON_TERRAIN
- | CMASK_WORM_USING_WEAPON
- | CMASK_WORM_IN_MIDAIR
- | CMASK_WORM_ON_ROPE
- | CMASK_WORM_FROZEN
- | CMASK_CRATE
- | CMASK_DONORCARD
- | CMASK_OILDRUM
- | CMASK_SKIMMING;
- }
- PXS : Library Code :
- int CGOBJECT_LAYER_OVERRIDE;
- int CGOBJECT_MASKINDEX_OVERRIDE;
- void layer_override::FirstFrame()
- {
- CGOBJECT_LAYER_OVERRIDE = -1;
- CGOBJECT_MASKINDEX_OVERRIDE = -1;
- }
- void SetLayerOverride(int layer)
- {
- CGOBJECT_LAYER_OVERRIDE = layer;
- }
- void SetMaskIndexOverride(int maskIndex)
- {
- CGOBJECT_MASKINDEX_OVERRIDE = maskIndex;
- }
- override CGObject::CGObject(CObject *parent, int layer, int maskIndex)
- {
- if(CGOBJECT_LAYER_OVERRIDE > 0)
- {
- layer = CGOBJECT_LAYER_OVERRIDE;
- CGOBJECT_LAYER_OVERRIDE = -1;
- }
- if(CGOBJECT_MASKINDEX_OVERRIDE > 0)
- {
- maskIndex = CGOBJECT_MASKINDEX_OVERRIDE;
- CGOBJECT_MASKINDEX_OVERRIDE = -1;
- }
- super;
- }
- PXS : Library Code :
- EMType M_TOUCHSENSOR;
- EMType M_TOUCHSENSOR_COLLIDE;
- CTouchSensor : CGObject;
- CTouchSensorParent : CObject;
- CTouchSensorParent * TSensorParent;
- CColMask* terrainColMask;
- void ldetector_script::Init()
- {
- M_TOUCHSENSOR = RegisterPXMessage();
- M_TOUCHSENSOR_COLLIDE = RegisterPXMessage();
- TSensorParent = new CTouchSensorParent;
- terrainColMask = CColMask(NullObj);
- }
- CTouchSensorParent::CTouchSensorParent()
- {
- super(NullObj, GS); //GS is not initialized there.. but who cares
- activatorObj = CGObject(NullObj);
- isCheckCollision = false;
- }
- /*
- int CTouchSensorParent::Check(int x,int y,CColMask* trg)
- {
- if (!isCheckCollision) return 0;
- for (local i = 0;i < Childs.Count; i++)
- {
- local ts = CTouchSensor(Childs.Objs[i]);
- if (trg->Check(x, y, ts->ColMask, ts->PosX, ts->PosY))
- {
- if (activatorObj != NullObj)
- {
- ts->activator = activatorObj;
- ts->noCollide = false;
- CMessageData mData;
- ts->notify->Message( ts, M_TOUCHSENSOR, 1032, &mData);
- if (ts->noCollide) return -1;
- }
- return 1;
- }
- }
- return 0;
- } */
- CTouchSensor::CTouchSensor(CObject* notifyTo, int x, int y, int sx, int sy)
- {
- super(Root, 1, 9);
- ClType = EObjectClass(4020);
- terrain = CGObject( Env->Objs.Objs[0] );
- Env->ObjsL[1].Remove(this); //some zhl for the win
- Env->ObjsL[1].Remove(terrain);
- Env->ObjsL[1].Compact();
- Env->ObjsL[1].Add(this);
- Env->ObjsL[1].Add(terrain);
- terrainColMask = CGObject(Env->Objs.Objs[0])->ColMask;
- noCollide = false;
- if ( (x + sx) > GG->land->BitMask->SX ) sx = x - GG->land->BitMask->SX;
- if ( (y + sy) > GG->land->BitMask->SY ) sy = y - GG->land->BitMask->SY;
- if ( x < 0 )
- {
- sx += x;
- x = 0;
- }
- if ( y < 0 )
- {
- sy += y;
- y = 0;
- }
- if ( (sx <= 0) || (sy <= 0) )
- {
- PosX = -1000; PosY = -1000;
- return;
- }
- bMask = new CBitmap1(sx, sy);
- for (local cx = 0; cx < sx; cx++)
- {
- for (local cy = 0; cy < sy; cy++)
- {
- bMask->SetPixel(cx, cy, GG->land->BitMask->GetPixel( cx+x, cy+y));
- }
- }
- // GG->land->BitMask->Rect(x, y, sx+x, sy+y, 0); // for ropez!
- ColMask = new CColMask(0, 0, bMask);
- notify = notifyTo;
- PosX = x;
- PosY = y;
- Stopped = false;
- // GravityFactor = 0;
- IsMaterial = true;
- IsStatic = true;
- aObjs = new CGObject*[10];
- aCObjs = new bool[10];
- maxObjects = 10;
- nObjects = 0;
- }
- /*
- override bool CColMask::Check(int x,int y,CColMask* trg,int trgx,int trgy)
- {
- local ans = 0;
- if (trg == terrainColMask)
- {
- ans = TSensorParent->Check(x, y, this);
- } else if (this == terrainColMask)
- {
- ans = TSensorParent->Check(trgx, trgy, trg);
- }
- if (ans > 0)
- {
- return true;
- } else if (ans < 0) return false;
- return super;
- } */
- void CTouchSensor::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if (Type == M_FRAME)
- {
- if (nObjects > 0)
- {
- if (notify != NullObj)
- {
- CMessageData mData;
- for (local i = 0; i < nObjects; i++)
- {
- activator = aObjs[i];
- notify->Message( this, M_TOUCHSENSOR, 1032, &mData);
- }
- }
- nObjects = 0;
- }
- }
- }
- override CGObject* CEnv::CheckCollisionEx(CGObject* obj,fixed x,fixed y,CColMask* mask,int colflags)
- {
- local res = super;
- if (res != NullObj)
- {
- if (res->ClType == EObjectClass(4020))
- {
- local ts = CTouchSensor(res);
- ts->activator = obj;
- for (local i = 0; i < ts->nObjects; i++)
- {
- if (ts->aObjs[i] == obj)
- {
- if (ts->aCObjs[i])
- {
- return NullObj;
- } else {
- return ts->terrain;
- }
- }
- }
- CMessageData mData;
- mData.params[0] = 0;
- obj->Message( ts, M_TOUCHSENSOR_COLLIDE, 1032, &mData);
- if (ts->nObjects < ts->maxObjects)
- {
- ts->aObjs[ts->nObjects] = obj;
- ts->aCObjs[ts->nObjects] = mData.params[0] != 0;
- ts->nObjects++;
- }
- if (mData.params[0] != 0) return NullObj;
- return ts->terrain;
- }
- }
- return res;
- }
- bool CTouchSensor::Reflect(CGObject* Obj,int type)
- {
- return false;
- }
- PXS : Library Code :
- require utils;
- CAntiGlitch* ggAg;
- void antiglitch_s::Init()
- {
- ggAg = new CAntiGlitch;
- }
- CAntiGlitch::CAntiGlitch()
- {
- lTime = 0;
- cState = 0;
- gTime = 0;
- rTime = 0;
- }
- void CAntiGlitch::Frame()
- {
- if ( (lTime == Root->Timer) && (rTime == Root->RetreatTimer) )
- {
- gTime += 20;
- if (gTime > 20000)
- {
- if (cState == 0)
- {
- //shake all objects first
- ShowMessage("Antiglitch Stage One");
- for (local i = 1; i < Env->Objs.Count; i++)
- {
- local obj = CGObject(Env->Objs.Objs[i]);
- if (obj == NullObj) continue;
- local shake = obj->IsMoving();
- if (!shake) continue;
- if (obj is CMissile)
- {
- missile = CMissile(obj);
- missile->ExplodeAt(missile->PosX, missile->PosY);
- missile->Free(true);
- continue;
- }
- obj->SpX = GS->GetRandom() % 200 - 100;
- obj->SpY = GS->GetRandom() % 200 - 100;
- }
- cState = 1;
- gTime = 10000;
- } else if (cState == 1)
- {
- ShowMessage("Antiglitch Stage Two");
- //delete objects to hell
- for (local i = 1; i < Env->Objs.Count; i++)
- {
- local obj = CGObject(Env->Objs.Objs[i]);
- if (obj == NullObj) continue;
- if (obj->ClType == OC_Worm) continue;
- if (!obj->IsMoving()) continue;
- obj->Free(true);
- }
- cState = 2;
- gTime = 10000;
- } else if (cState == 2)
- {
- ShowMessage("Antiglitch Stage Three");
- //shake everything
- for (local i = 1; i < Env->Objs.Count; i++)
- {
- local obj = CGObject(Env->Objs.Objs[i]);
- if (obj == NullObj) continue;
- obj->SpX = GS->GetRandom() % 200 - 100;
- obj->SpY = GS->GetRandom() % 200 - 100;
- if (obj is CMissile)
- {
- missile = CMissile(obj);
- missile->Free(true);
- continue;
- }
- }
- cState = 3;
- gTime = 10000;
- } else if (cState == 3)
- {
- cState = 4;
- ShowMessage("Antiglitch Stage Four");
- Root->Message( Root, M_SKIPTURN, 0, NullObj);
- }
- }
- } else {
- gTime = 0;
- cState = 0;
- lTime = Root->Timer;
- rTime = Root->RetreatTimer;
- }
- }
- override void CWorm::FireFinal(CWeapon* Weap,CShootDesc* Desc)
- {
- super;
- ggAg->gTime = 0;
- ggAg->cState = 0;
- }
- override void CWorm::SetState(EObjState State)
- {
- if (State == WS_DEAD)
- {
- ggAg->gTime = 0;
- ggAg->cState = 0;
- }
- super;
- }
- override void CTurnGame::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- super;
- if (Type == M_FRAME)
- {
- ggAg->Frame();
- }
- }
- PXS : Library Code :
- require utils;
- $editor
- $object LightSource
- $origin -15 -15
- $image "edcross.png"
- $radius 17
- $func SpawnLightSource
- $autoname LSource
- $param Radius radius 50
- $param FalloffRadius radius 75
- $param Intensity int 100
- $object_end
- $object FoWControl
- $origin -15 -15
- $image "edfowcontrol.png"
- $radius 17
- $func SpawnFoWControl
- $param Enable bool true
- $param WormLightRadius int 50
- $param WormLightFRadius int 110
- $object_end
- $end
- CDarknessControl* darkControl;
- #DARKNESS
- enum DCLightType = (DCL_OMNI, DCL_DIRECT);
- void darkness_script::Init()
- {
- darkControl = new CDarknessControl;
- }
- void SpawnLightSource(CEditorObject* obj)
- {
- darkControl->SetLight(obj->PosX, obj->PosY, obj->GetInt("Radius"),
- obj->GetInt("FalloffRadius"), obj->GetInt("Intensity")/100.0);
- darkControl->sSources = darkControl->nSources;
- }
- CDarknessControl::CDarknessControl()
- {
- enabled = false;
- initialized = false;
- seeAll = false;
- lSource = new CLightSource[512];
- sSources = 0;
- wLightRadius = 50;
- wLightFRadius = 110;
- }
- void DarknessControl_Render()
- {
- darkControl->Draw();
- }
- bool CDarknessControl::IsColorVisible(int clr)
- {
- if (IsReplay() || seeAll) return true;
- if (IsMultiplayer())
- {
- if (GG->machColors[GetLocalMachine()] & (1 << clr))
- {
- return true;
- }
- } else {
- if (clr == GetTeamColor(Root->CurTeam))
- {
- return true;
- }
- }
- return false;
- }
- bool CDarknessControl::IsTeamVisible(int team)
- {
- return IsColorVisible(GetTeamColor(team));
- }
- bool CDarknessControl::DoIKnowHim(CWorm* worm)
- {
- if (!enabled) return true;
- return IsTeamVisible(worm->WormTeam);
- }
- override void CWorm::RenderLabels()
- {
- if (darkControl->DoIKnowHim(this) || (DC_LightTimer > 0) ) super;
- DC_LightTimer -= 1;
- } /*
- override void CWorm::RenderDmgLabel()
- {
- if (darkControl->DoIKnowHim(this)) super;
- } */
- override void CWorm::RenderCrosshair()
- {
- if (darkControl->DoIKnowHim(this)) super;
- }
- override void CDDQueue::AddSprite(fixed z,fixed x,fixed y,int unk,int sprite,fixed frame)
- {
- if (!darkControl->enabled || darkControl->seeAll || !IsMultiplayer())
- {
- super;
- return;
- }
- local sIndex = sprite & 65535;
- if (sIndex >= 20 && sIndex <= 25)
- {
- if (GG->machColors[GetLocalMachine()] & (1 << (sIndex - 20)) )
- {
- super;
- }
- return;
- }
- super;
- }
- override void CObject::ForceFocus(fixed x,fixed y)
- {
- if (!IsMultiplayer() || darkControl == NullObj || !darkControl->enabled)
- {
- super;
- } else {
- if (ClType == OC_Team)
- {
- local tm = CTeam(this);
- if (GG->machColors[GetLocalMachine()] & (1 << GetTeamColor(tm->Index)))
- {
- super;
- }
- }
- if (ClType == OC_Worm)
- {
- local wm = CWorm(this);
- if (GG->machColors[GetLocalMachine()] & (1 << GetTeamColor(wm->WormTeam)))
- {
- super;
- }
- }
- }
- }
- override void CGObject::LookAtMe(fixed x,fixed y,int priority)
- {
- if (!IsMultiplayer() || darkControl == NullObj || !darkControl->enabled)
- {
- super;
- } else {
- if (ClType == OC_Worm)
- {
- local wm = CWorm(this);
- if (GG->machColors[GetLocalMachine()] & (1 << GetTeamColor(wm->WormTeam)))
- {
- super;
- }
- }
- }
- }
- void CDarknessControl::Init()
- {
- bSize = 12;
- nBlX = GS->Disp->xRes / bSize + 4;
- nBlY = GS->Disp->yRes / bSize + 4;
- lOutRGB = new int[nBlX*nBlY];
- initialized = true;
- if (IsMultiplayer())
- {
- if ((GG->machColors[GetLocalMachine()] & (1+2+4+8+16+32)) == 0) enabled = false;
- }
- }
- void CDarknessControl::SetLight(float x, float y, float rad, float rad2, float intens)
- {
- if (nSources == 512) return;
- lSource[nSources].x = x;
- lSource[nSources].y = y;
- lSource[nSources].rad = rad;
- lSource[nSources].rad2 = rad2;
- lSource[nSources].rads = rad * rad;
- lSource[nSources].rad2s = rad2 * rad2;
- lSource[nSources].intens = intens;
- lSource[nSources].radds = rad2 * rad2 - rad * rad;
- lSource[nSources].type = DCL_OMNI;
- nSources++;
- }
- void CDarknessControl::SetDirectionalLight(float x1, float y1, float x2, float y2, float spread, float dSpread, float intens, float intensFall)
- {
- if (nSources == 512) return;
- local ds = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); //normalization factor
- if (ds == 0) return;
- lSource[nSources].a = (y1 - y2) / ds;
- lSource[nSources].b = (x2 - x1) / ds;
- lSource[nSources].c = -(x1 * (y1 - y2) + y1 * (x2 - x1)) / ds;
- lSource[nSources].c2 = -(x1 * (x2 - x1) - y1 * (y1 - y2)) / ds;
- lSource[nSources].x = x1;
- lSource[nSources].y = y1;
- lSource[nSources].rad = ds;
- lSource[nSources].rad2 = spread;
- lSource[nSources].rad2s = dSpread;
- lSource[nSources].rads = (ds * dSpread + spread) / 3.0;
- lSource[nSources].radsr = ds * dSpread + spread;
- lSource[nSources].intens = intens;
- lSource[nSources].intens2 = intensFall;
- lSource[nSources].type = DCL_DIRECT;
- nSources++;
- }
- void CDarknessControl::DoFlashlight(CGObject* fromObj, float x1, float y1, float dx, float dy, float maxDist)
- {
- local xr = 0; local yr = 0;
- local cObj = TraceLine(fromObj, x1, y1, x1 + dx * maxDist, y1 + dy * maxDist, -1, &xr, &yr);
- local ds = (xr - x1) * (xr - x1) + (yr - y1) * (yr - y1);
- if (cObj != NullObj && ds < 40000)
- {
- if (cObj->ClType == OC_Worm)
- {
- local wm = CWorm(cObj);
- wm->DC_LightTimer = 3;
- }
- }
- SetDirectionalLight(x1, y1, xr, yr, 25, 0.35, 0.8, 0.7 / maxDist);
- }
- void CDarknessControl::GenerateLSources()
- {
- nSources = sSources;
- for (local i = 1; i < Env->Objs.Count; i++)
- {
- local obj = CGObject(Env->Objs.Objs[i]);
- if (obj == NullObj) continue;
- if (obj->ClType == OC_Worm)
- {
- local wm = CWorm(obj);
- local lit = DoIKnowHim(wm);
- if (!lit) continue;
- SetLight(obj->PosX, obj->PosY, wLightRadius, wLightFRadius, 0.9);
- if (wm->ObjState == WS_AIMING || wm->ObjState == WS_SETPOWER || wm->ObjState == WS_FIRED || wm->ObjState == WS_FIRECONT)
- {
- local ang = (1 - wm->FireAngle) * 3.14159;
- if (wm->TurnSide < 0)
- {
- ang = 6.28318 - ang;
- }
- DoFlashlight(wm, wm->PosX, wm->PosY, sin(ang), -cos(ang), 1000);
- }
- }
- }
- }
- void CDarknessControl::GetLightIntensity(float x, float y, float* R, float* G, float* B)
- {
- local oR = 0.0; local oG = 0.0; local oB = 0.0;
- for (local i = 0; i < nSources; i++)
- {
- local dx = x - lSource[i].x;
- local dy = y - lSource[i].y;
- local ds = dx * dx + dy * dy;
- if (lSource[i].type == DCL_OMNI)
- {
- if (ds < lSource[i].rad2s)
- {
- if (ds < lSource[i].rads)
- {
- oR = oR + lSource[i].intens; oG = oG + lSource[i].intens; oB = oB + lSource[i].intens;
- } else {
- local coef = (1.0 - (ds - lSource[i].rads) / lSource[i].radds) * lSource[i].intens;
- oR += coef; oG += coef; oB += coef;
- }
- }
- } else {
- local v1 = x * lSource[i].b - y * lSource[i].a + lSource[i].c2;
- if (v1 >= 0)
- {
- local sp = 0.0; local coef2 = 1.0;
- if (v1 <= lSource[i].rad)
- {
- sp = lSource[i].rad2 + v1 * lSource[i].rad2s;
- } else {
- if (v1 <= (lSource[i].rad + lSource[i].rads))
- {
- local coef2 = 1.0 - (v1 - lSource[i].rad) / lSource[i].rads;
- sp = lSource[i].radsr * sqrt(coef2);
- } else continue;
- }
- if (sp > 0.0)
- {
- sp = sp + 0.5;
- local v2 = abs(x * lSource[i].a + y * lSource[i].b + lSource[i].c);
- local coef = 1 - v2 / sp;
- if (coef > 0.0)
- {
- local intens = lSource[i].intens - lSource[i].intens2 * v1;
- if (intens > 0.0)
- {
- coef = coef * intens * coef2;
- oR += coef; oG += coef; oB += coef;
- }
- }
- }
- }
- }
- }
- *R = oR; *G = oG; *B = oB;
- }
- void CDarknessControl::Draw()
- {
- if (!initialized) Init();
- GenerateLSources();
- local i = 0; // i don't trust EAX to do typecasting :D
- local offX = -float( int(int(GS->ActCameraX) % bSize) ) + GS->ActCameraX - GS->Disp->halfX - bSize;
- local offY = -float( int(int(GS->ActCameraY) % bSize) ) + GS->ActCameraY - GS->Disp->halfY - bSize;
- local IntensityR = 0.0;
- local IntensityG = 0.0;
- local IntensityB = 0.0;
- for (local cy = 0; cy < nBlY; cy++)
- {
- local cOffX = offX;
- local cOffY = cy * bSize + offY;
- for (local cx = 0; cx < nBlX; cx++)
- {
- GetLightIntensity(cOffX, cOffY, &IntensityR, &IntensityG, &IntensityB);
- local R = int(IntensityR * 255.0);
- if (R > 255) R = 255;
- local G = int(IntensityG * 255.0);
- if (G > 255) G = 255;
- local B = int(IntensityB * 255.0);
- if (B > 255) B = 255;
- lOutRGB[i] = RGB(R,G,B);
- i++;
- cOffX += bSize;
- }
- }
- CQuad q;
- i = 0;
- q.tex = 0;
- q.blend = 64; //color blending
- for (local j = 0; j < 4; j++)
- {
- q.v[j].tx = 0; q.v[j].ty = 0;
- }
- for (local cy = 0; cy < (nBlY-1); cy++)
- {
- local cOffX = offX;
- local cOffY = cy * bSize + offY;
- for (local cx = 0; cx < (nBlX-1); cx++)
- {
- q.v[0].x = cOffX;
- q.v[0].y = cOffY;
- q.v[1].x = cOffX + bSize;
- q.v[1].y = cOffY;
- q.v[2].x = cOffX + bSize;
- q.v[2].y = cOffY + bSize;
- q.v[3].x = cOffX;
- q.v[3].y = cOffY + bSize;
- q.v[0].color = lOutRGB[i];
- q.v[1].color = lOutRGB[i+1];
- q.v[2].color = lOutRGB[i+nBlX+1];
- q.v[3].color = lOutRGB[i+nBlX];
- RenderQuad(&q, 0);
- i++;
- cOffX += bSize;
- }
- i++;
- }
- }
- void CDarknessControl::UpdateStatus()
- {
- if (seeAll || !enabled || !initialized) return;
- if (!IsMultiplayer()) return;
- local hOther = false;
- local hMy = false;
- for (local i = 1; i < Env->Objs.Count; i++)
- {
- local wm = CWorm(Env->Objs.Objs[i]);
- if (wm == NullObj) continue;
- if (wm->ClType != OC_Worm) continue;
- if (wm->ObjState == WS_DEATH) continue;
- if (GG->machColors[GetLocalMachine()] & (1 << GetTeamColor(wm->WormTeam)))
- {
- hMy = true;
- } else {
- hOther = true;
- }
- }
- if (!hMy) seeAll = true;
- if (!hOther) seeAll = true;
- }
- void CDarknessControl::Queue()
- {
- if (!enabled) return;
- Root->AddCustomRender(0.5, "DarknessControl_Render");
- }
- override void CTurnGame::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- super;
- if (Type == M_FRAME)
- {
- darkControl->UpdateStatus();
- }
- if (Type == M_DRAWQUEUE)
- {
- darkControl->Queue();
- }
- }
- void SpawnFoWControl(CEditorObject* obj)
- {
- if (obj->GetBool("Enable"))
- {
- darkControl->enabled = true;
- }
- darkControl->wLightRadius = obj->GetInt("WormLightRadius");
- darkControl->wLightFRadius = obj->GetInt("WormLightFRadius");
- }
- PXS : Library Code :
- require Utils;
- override CMine::CMine(CObject* Parent, CMineParams* Params, CShootDesc* Desc, bool Snap, int Unk)
- {
- if (Desc->Team >= 1)
- {
- Params->Radius = 1;
- if (Params->Fuse >= 0) {
- local AddFuse = GS->GetRandom() % 12 * 125;
- Params->Fuse = 750 + AddFuse;
- } else Params->Fuse = 0 - Params->Fuse;
- };
- super;
- };
- override void CMine::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if (Type != M_FRAME || InitParams.Radius != 1 || ClType != OC_Mine)
- {
- super;
- return;
- };
- if (Active != 0 || Prefuse > 0)
- {
- super;
- return;
- };
- for (local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if (obj == NullObj) continue;
- if (obj->ClType != OC_Worm) continue;
- local worm = CWorm(obj);
- if (GetTeamColor(ShootData.Team) == GetTeamColor(worm->WormTeam)) continue;
- if (DistBetweenObjs(obj, this) < 65)
- {
- Active = 1;
- nPulses = Fuse / 250;
- break;
- };
- };
- super;
- };
- override void CMine::Render()
- {
- if (InitParams.Radius == -1) return;
- if (InitParams.Radius == 1)
- {
- local Color = GetTeamColor(ShootData.Team);
- if (Color == 0)
- {
- SetColorMod(RGB(180, 0, 0), 4); //4 - diffuse color goes to smooth addition
- }
- if (Color == 1)
- {
- SetColorMod(RGB(0, 0, 180), 4);
- }
- if (Color == 2)
- {
- SetColorMod(RGB(0, 180, 0), 4);
- }
- if (Color == 3)
- {
- SetColorMod(RGB(120, 120, 0), 4);
- }
- if (Color == 4)
- {
- SetColorMod(RGB(120, 0, 120), 4);
- }
- if (Color == 5)
- {
- SetColorMod(RGB(0, 120, 120), 4);
- }
- };
- super;
- ClearColorMod();
- };
- PXS : Library Code : require utils;
- WindNade : CMissile;
- GravityNade : CMissile;
- StickyMine : CMine;
- MovingOilDrum : COilDrum;
- override void CWorm:: OnSink() { return; }
- StickyMine::StickyMine(CObject* Parent,CMineParams* Params,CShootDesc* SDesc,bool Snap,int Unk, CWorm *launcher)
- {
- super(Parent, Params, SDesc, Snap, Unk);
- stuck = false;
- released = false;
- launcher->stickyminedelete = false;
- if ((PosX != SDesc->X) || (PosY != SDesc->Y)) {
- launcher->nTotalShoots = 0;
- //WORKAROUND FOR EAX BUG
- launcher->stickyminedelete = true;
- return;
- }
- }
- void StickyMine::Collide(CGObject* Obj,int type)
- {
- super;
- if (released == false){
- if (stuck == false) {
- SpX = 0;
- SpY = 0;
- GravityFactor=0;
- stuck = true;
- }
- else {
- GravityFactor=1;
- released = true;
- }
- }
- }
- void StickyMine::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if (released == false){
- if (Type == M_FRAME) {
- if ( (stuck == true) && ((SpX != 0) || (SpY != 0)) ) {
- GravityFactor = 1;
- released = true;
- }
- }
- }
- super;
- }
- // WORKAROUND FOR WA BUG
- override void CWorm::CWorm(CObject* Parent,int aTeam,int aIndex,CWormParams* params)
- {
- super;
- stickyminefired = false;
- }
- // END OF WORKAROUND
- MovingOilDrum::MovingOilDrum(CObject *parent, CShootDesc *Sdesc, CWorm *launcher)
- {
- FreeMe = false;
- super(parent->GetObject(25, 0), Sdesc->X, Sdesc->Y, false);
- SpX = Sdesc->SpX;
- SpY = Sdesc->SpY;
- if ((PosX != Sdesc->X) || (PosY != Sdesc->Y)) {
- launcher->nAvalShoots = 1;
- launcher->nTotalShoots = 0;
- FreeMe = true;
- return;
- }
- }
- void MovingOilDrum::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if ((Type == M_FRAME) && FreeMe)
- {
- Free(true);
- return;
- }
- super;
- }
- WindNade::WindNade(CObject* parent,CWeaponLaunch* ldata,CShootDesc* sdata)
- {
- super;
- WindFactor = 1;
- }
- GravityNade::GravityNade(CObject* parent,CWeaponLaunch* ldata,CShootDesc* sdata)
- {
- super;
- GravityFactor = 2;
- }
- override void CWorm::FireFinal(CWeapon* Weap,CShootDesc* Desc)
- {
- if (Weap->CheckName("GravNade"))
- {
- new GravityNade(Root->GetObject(25, 0),&Weap->launch, Desc);
- return;
- }
- if (Weap->CheckName("WindNade"))
- {
- new WindNade(Root->GetObject(25, 0),&Weap->launch, Desc);
- return;
- }
- if(Weap->CheckName("J"))
- {
- SpX = Desc->SpX;
- SpY = Desc->SpY;
- return;
- }
- if (Weap->CheckName("StickyMine"))
- {
- // WORKAROUND FOR WA BUG
- // END OF WORKAROUND
- CMineParams MParams;
- zero(&MParams);
- MParams.Prefuse = 2500; //time before ability to activate
- MParams.Flags = 60; //flags of objects to react on
- MParams.Bias = 0; //Y shift of explosion
- MParams.Damage = 27; //damage
- MParams.BlastPower = 100;
- MParams.Fuse = 100;
- MParams.Radius = 40;
- local smine = new StickyMine(Root->GetObject(25, 0), &MParams, Desc, false, 0, this);
- if (stickyminedelete) //workaround for EAX bug
- {
- smine->Free(true);
- } else {
- if (!stickyminefired) {
- nTotalShoots = 0;
- stickyminefired = true;
- } else {
- stickyminefired = false;
- }
- }
- return;
- }
- if (Weap->CheckName("BarrelLauncher"))
- {
- new MovingOilDrum(Root->GetObject(25, 0), Desc, this);
- return;
- }
- super;
- }
- override void CMissile::ExplodeAt(fixed x,fixed y)
- {
- if (weap->CheckName("TeleNade")){
- currentworm = GetCurrentWorm();
- if (currentworm != NullObj){
- currentworm->PosX = x;
- currentworm->PosY = y-6;
- return;
- }
- return;
- // weapon = GetWeaponByName("Teleport");
- // shootdesc = new CShootDesc;
- // currentworm = GetCurrentWorm();
- // shootdesc->Team = currentworm->WormTeam;
- // shootdesc->Worm = currentworm->WormNumber;
- // shootdesc->AddX = x;
- // shootdesc->AddY = y;
- // shootdesc->X = currentworm->PosX;
- // shootdesc->Y = currentworm->PosY;
- // currentworm->FireFinal(weapon, shootdesc);
- // return;
- }
- super;
- }
- PXS : Library Code :
- require Utils;
- CTurretBase : CGObject;
- CSprite* turretSprite;
- CSprite* turretSpriteB;
- void turretbase::InitGraphic()
- {
- local f = GetAttachment("turretbase.png");
- turretSprite = LoadSprite(f, 1, 0);
- local f = GetAttachment("turrenttower.png");
- turretSpriteB = LoadSprite(f, 1, 0);
- };
- void turretbase::FirstFrame()
- {
- local envfilter = CFilter(Root->GetObject(25, 0));
- envfilter->Allow(M_TURNBEGIN);
- };
- CTurretBase::CTurretBase(CObject* parent, fixed x, fixed y)
- {
- super(parent, 17, 9); //barrel's collsion mask
- PosX = x;
- PosY = y;
- SpX = 0;
- SpY = 0;
- ColGroup = 6190;
- DumpingB = 0.5;
- IsMaterial = true;
- SpeedDivider = 1;
- TargetObj = CGObject(NullObj);
- baseSprite = turretSprite;
- towerSprite = turretSpriteB;
- ClType = EObjectClass(500);
- gFactor = 1.0;
- towerOffset = 25;
- thinkingTime = 15;
- curThink = 0;
- dontShoot = false;
- timeForShoot = 15.0; //time, need for ballistic solving
- minimalRadius = 40;
- sensorRadius = 350;
- lostRadius = 450;
- turretangle = 1.57;
- angToShoot = 0.0;
- turretdir = 1;
- reloadState = 0;
- reloadTime = 30;
- initalRTime = 20;
- stepRTime = 1.12;
- shootPower = 0.0;
- timeForShoot = 32.0;
- turretTeam = -1;
- ammoPerTurn = 5;
- towerlen = 10;
- local FourCheck = MakeCircleMask(3);
- FourCheckMask = new CColMask(0, 0, FourCheck);
- breakable = false;
- health = 50;
- maxHealth = health;
- ExpDamage = 50;
- speed = 0.08;
- };
- void CTurretBase::GetShootAngle()
- {
- local tm = timeForShoot;
- local x = TargetObj->PosX - PosX;
- local rx = x / timeForShoot;
- local y = TargetObj->PosY - (PosY - towerOffset);
- local ry = SolveBallistic(y, timeForShoot, Env->Gravity * gFactor);
- angToShoot = 0.0;
- if (rx > 0)
- {
- angToShoot = atan2(rx, 0 - ry);
- turretdir = 1;
- } else {
- angToShoot = atan2(0 - rx, 0 - ry);
- turretdir = -1;
- };
- shootPower = sqrt(rx * rx + ry * ry);
- lrx = rx;
- lry = ry;
- };
- bool CTurretBase::CheckTrace()
- {
- local trtime = timeForShoot;
- local a = 0;
- local HObj = BTrace(this, FourCheckMask, PosX, PosY - towerOffset, lrx, lry, Env->Gravity * gFactor, trtime - 1, 1, &a);
- if (CObject(HObj) == Env->Objs.Objs[0]) return true;
- return false;
- };
- bool CTurretBase::AimToEnemy()
- {
- DistToEnemy = DistBetweenObjs(this, TargetObj);
- if (DistToEnemy > lostRadius)
- {
- TargetObj = NullObj;
- return false;
- };
- local ang = 0.0;
- //MY RULE FOR ARCTAN
- //a = sin(ang)
- //b = cos(ang)
- //ang = atan2(a, b);
- GetShootAngle();
- local ang = angToShoot;
- if (abs(ang - turretangle) > (speed * 2) )
- // if (false)
- {
- if (ang > turretangle)
- {
- turretangle = turretangle + speed;
- } else {
- turretangle = turretangle - speed;
- };
- return false;
- } else {
- turretangle = ang;
- if (dontShoot) return false;
- return true;
- };
- };
- void CTurretBase::UpdateTime()
- {
- timeForShoot += 10.0;
- timeForShoot = timeForShoot * 1.1;
- if (timeForShoot > 100.0) timeForShoot = 16.0;
- };
- void CTurretBase::FillShootingInfo()
- {
- ShootX = PosX + sin(turretangle) * turretdir * towerlen;
- ShootY = (PosY - towerOffset) - cos(turretangle) * towerlen;
- ShootSX = sin(turretangle) * turretdir;
- ShootSY = 0.0 - cos(turretangle);
- UpdateTime();
- };
- bool CTurretBase::ShootAtEnemy()
- {
- // PrintMessage(2);
- return true;
- };
- void CTurretBase::FindTarget()
- {
- for (local i = 1; i < Env->Objs.Count; i+=1)
- {
- local Obj = Env->Objs.Objs[i];
- if (Obj == NullObj) continue;
- if (Obj->ClType != OC_Worm) continue;
- local Worm = CWorm(Obj);
- if (turretTeam >= 0)
- {
- local tColor = GetTeamColor(Worm->WormTeam);
- if (tColor == GetTeamColor(turretTeam)) continue;
- };
- if (Worm->ObjState != WS_WALKING)
- {
- if ((Worm->SpX == 0) && (Worm->SpY == 0)) continue;
- }
- if (GS->Info.GetWormHealth(Worm->WormTeam,Worm->WormNumber) <= 0) continue;
- local CatX = Worm->PosX - PosX;
- local CatY = Worm->PosY - (PosY - towerOffset);
- local Dist = sqrt(CatX * CatX + CatY * CatY);
- if (Dist < minimalRadius) continue;
- if (Dist < sensorRadius)
- {
- if (srandom_p() < 0.3)
- {
- if (Obj != TargetObj)
- {
- TargetObj = Obj;
- PRegister(&TargetObj);
- };
- };
- };
- };
- };
- bool CTurretBase::ApplyDamage(int dmg)
- {
- if (breakable == false) return false;
- health -= dmg;
- if (health <= 0)
- {
- DoExplosion(PosX,PosY, 100, ExpDamage, 0, 0);
- Free(true);
- return true;
- }
- return false;
- }
- void CTurretBase::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if (breakable && (health <= 0)) return;
- if (Type == M_FRAME)
- {
- if (reloadState > 0) reloadState -= 1;
- if (Root->IsTimerActive() == false)
- {
- super;
- return;
- };
- if (ammoCurrent <= 0)
- {
- super;
- return;
- }
- if (TargetObj == NullObj)
- {
- FindTarget();
- curThink = thinkingTime;
- } else {
- if (curThink > 0)
- {
- curThink = curThink - 1;
- } else {
- if (AimToEnemy())
- {
- if (reloadState == 0)
- {
- if (CheckTrace())
- {
- if (srandom_p() < 0.65)
- {
- UpdateTime();
- curThink = 4;
- } else {
- TargetObj = NullObj;
- curThink = 10;
- return;
- };
- reloadState = reloadTime;
- return;
- };
- FillShootingInfo();
- if (ShootAtEnemy())
- {
- reloadState = reloadTime;
- reloadTime = int(reloadTime * stepRTime);
- ammoCurrent -= 1;
- } else {
- TargetObj = NullObj;
- curThink = 10;
- return;
- }
- };
- };
- };
- };
- };
- if (Type == M_DRAWQUEUE)
- {
- local colorCoef = health / maxHealth * 0.75 + 0.25;
- int r; int g; int b;
- GetTeamColorRGB(GetTeamColor(turretTeam)+1, &r, &g, &b);
- if (r < 128) r = 128;
- if (g < 128) g = 128;
- if (b < 128) b = 128;
- SetColorMod(RGB(colorCoef * r, colorCoef * g, colorCoef * b), 0);
- AddSprite(12, PosX, PosY, 0, baseSprite->Index, 0);
- local spr = towerSprite->Index;
- local ang = turretangle;
- if (turretdir < 0)
- {
- spr = spr + 262144;
- ang = 3.1415 - ang;
- };
- // local ang = turretangle;
- // if (turretdir < 0) ang = ang + 1.5707;
- AddSpriteEx(11, PosX, PosY - towerOffset, spr, 0, ang - 1.5707, 1);
- ClearColorMod();
- };
- if (Type == M_TURNBEGIN)
- {
- reloadTime = initalRTime;
- ammoCurrent = ammoPerTurn;
- TargetObj = CGObject(NullObj);
- }
- if (breakable)
- {
- if (Type == M_EXPLOSION)
- {
- local dx = MData->fparams[1] - PosX;
- local dy = MData->fparams[2] - PosY;
- local dist = dx*dx + dy*dy;
- local dmgcoef = 1 - dist / (MData->params[4] * MData->params[4] * 4);
- if (dmgcoef > 0)
- {
- if (ApplyDamage(dmgcoef * MData->params[4])) return;
- }
- }
- if (Type == M_GUNEXP)
- {
- if (sender is CArrow)
- {
- if (CArrow(sender)->TeamIndex == turretTeam)
- {
- return;
- }
- }
- if (ApplyDamage(MData->params[5])) return;
- }
- }
- super;
- };
- PXS : Library Code :
- $editor
- $object MineTurret
- $origin -20 -25
- $radius 28
- $image "edturret.png"
- $func SpawnTurret
- $param Invincible bool false
- $param Mounted bool false
- $param ClearMines bool true
- $param AmmoPerTurn int 9999
- $object_end
- $end
- CSprite* mineturretBase;
- CSprite* mineturretTower;
- void mineturret::InitGraphic()
- {
- local f = GetAttachment("baseminez.png");
- mineturretBase = LoadSprite(f, 1, 0);
- local f = GetAttachment("towerminez.png");
- mineturretTower = LoadSprite(f, 1, 0);
- }
- CMineTurret : CTurretBase;
- void CMineTurret::CMineTurret(CObject* parent, fixed x, fixed y)
- {
- super;
- breakable = true;
- clearMines = false;
- baseSprite = mineturretBase;
- towerSprite = mineturretTower;
- };
- bool CMineTurret::ShootAtEnemy()
- {
- if (CheckMaskAt(this, FourCheckMask, ShootX, ShootY, -1) != NullObj) return false;
- CMineParams MParams;
- CShootDesc SDesc;
- zero(&MParams);
- zero(&SDesc);
- local ForceVar = GS->GetRandom() % 64;
- local BaseForce = shootPower - 0.1 + ForceVar / 96.0;
- SDesc.Team = turretTeam;
- SDesc.X = ShootX;
- SDesc.Y = ShootY;
- if (turretTeam < 0) SDesc.Team = 0;
- SDesc.SpX = ShootSX * BaseForce;
- SDesc.SpY = ShootSY * BaseForce;
- MParams.Prefuse = 0;
- MParams.Flags = 60;
- MParams.Bias = 0;
- MParams.Damage = 50;
- MParams.BlastPower = 100;
- MParams.Fuse = 400; //20 frames
- MParams.Radius = 48;
- local Mine = new CMine(Root->GetObject(25, 0), &MParams, &SDesc, false, 0);
- Mine->autoTurnDestruct = clearMines;
- return true;
- };
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if (Weap->CheckName("Mine Turret"))
- {
- local sg = new CMineTurret(GetObject(25, 0), PosX + 15 * TurnSide, PosY - 50);
- sg->turretTeam = WormTeam;
- sg->ammoPerTurn = 6;
- } else {
- super;
- };
- };
- void SpawnTurret(CEditorObject* eobj)
- {
- local sg = new CMineTurret(Root->GetObject(25, 0), eobj->PosX, eobj->PosY);
- sg->turretTeam = -1;
- sg->clearMines = eobj->GetBool("ClearMines");
- sg->ammoPerTurn = eobj->GetInt("AmmoPerTurn");
- if (eobj->GetBool("Invincible"))
- {
- sg->breakable = false;
- }
- if (eobj->GetBool("Mounted"))
- {
- sg->SpeedDivider = 32767;
- for (local i = 0; i < 100; i++)
- {
- if (Env->CheckCollision(sg, sg->PosX, sg->PosY + 1) != NullObj) break;
- sg->PosY += 1;
- }
- }
- };
- PXS : Library Code :
- require utils;
- CArrowTurret : CTurretBase;
- bool AT_DontDrawLand;
- CSprite* arrturretBase;
- CSprite* arrturretTower;
- void arrowturret::InitGraphic()
- {
- local f = GetAttachment("balbase.png");
- arrturretBase = LoadSprite(f, 1, 0);
- local f = GetAttachment("baltower.png");
- arrturretTower = LoadSprite(f, 1, 0);
- }
- override void CLandscape::ApplyBitmap(int x,int y,int sx,int sy,CBitmap* bm,CBitmap* bm2,int srcX,int srcY)
- {
- if (AT_DontDrawLand) return;
- super;
- }
- override CArrow::CArrow(CObject* Parent,int* damage,CShootDesc* desc)
- {
- DontStick = false;
- super;
- }
- override void CArrow::Message(CObject* sender,EMType Type,int MSize,CMessageData* MData)
- {
- if (DontStick)
- {
- AT_DontDrawLand = true;
- super;
- AT_DontDrawLand = false;
- } else {
- super;
- }
- }
- void CArrowTurret::CArrowTurret(CObject* parent, fixed x, fixed y)
- {
- super;
- gFactor = 0.25;
- ColGroup = ColGroup & (-65537); //remove Arrows flag
- breakable = true;
- towerlen = 16;
- ammoPerTurn = 8;
- baseSprite = arrturretBase;
- towerSprite = arrturretTower;
- };
- bool CArrowTurret::AimToEnemy()
- {
- if (TargetObj != NullObj)
- {
- local l = DistBetweenObjs(TargetObj, this);
- timeForShoot = l / 10 + 1; //500 pixels per sec, rait
- }
- return super;
- }
- bool CArrowTurret::ShootAtEnemy()
- {
- if (CheckMaskAt(Root, FourCheckMask, ShootX, ShootY, -65537) != NullObj) return false;
- CShootDesc SDesc;
- zero(&SDesc);
- local ForceVar = GS->GetRandom() % 64;
- local BaseForce = shootPower - 0.1 + ForceVar / 96.0;
- SDesc.Team = turretTeam; //no more //fixin rare CArrow crash bug.
- SDesc.Worm = 0;
- SDesc.X = ShootX;
- SDesc.Y = ShootY;
- if (turretTeam < 0) SDesc.Team = 0; //wtf
- SDesc.SpX = ShootSX * BaseForce;
- SDesc.SpY = ShootSY * BaseForce;
- local admg = 10;
- local arrow = new CArrow(Root->GetObject(25, 0), &admg, &SDesc);
- if (CGObject(arrow)->IsValid())
- {
- arrow->GravityFactor = 0.25;
- arrow->DontStick = true;
- }
- return true;
- };
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if (Weap->CheckName("Auto-ballista"))
- {
- local sg = new CArrowTurret(GetObject(25, 0), PosX + 15 * TurnSide, PosY - 50);
- sg->turretTeam = WormTeam;
- } else {
- super;
- };
- };
- PXS : Library Code :
- require utils;
- PxParticleManager : CObject
- PxParticle : CObject
- PxParticleManager *PM;
- void particle::FirstFrame()
- {
- PM = new PxParticleManager();
- }
- PxParticleManager::PxParticleManager()
- {
- super(Root, GS);
- }
- void __DrawPxParticles()
- {
- PM->Draw();
- }
- void PxParticleManager::Draw()
- {
- for(int i=0 ; i<Childs.Count ; i+=1)
- {
- local p = PxParticle(Childs.Objs[i]);
- if(p == PxParticle(NullObj)) continue;
- p->Draw();
- }
- }
- void PxParticleManager::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- super;
- }
- if(Type == M_DRAWQUEUE)
- {
- AddCustomRender(6, "__DrawPxParticles");
- }
- if(Type == M_FRAME)
- {
- for(int i=0 ; i<Childs.Count ; i+=1)
- {
- local p = PxParticle(Childs.Objs[i]);
- if(p == PxParticle(NullObj)) continue;
- if(p->Dead)
- {
- p->Free(true);
- break;
- }
- }
- }
- }
- PxParticle::PxParticle(int sprite, float x, float y)
- {
- super(PM, GS);
- PosX = x;
- PosY = y;
- SpX = 0.0;
- SpY = 0.0;
- Sprite = sprite;
- AirResistance = 0.0;
- LifeTime = 50;
- StartR = 255; StartG = 255; StartB = 255; StartA = 255;
- EndR = 255; EndG = 255; EndB = 255; EndA = 0;
- StartSizeX = 1.0;
- StartSizeY = 1.0;
- EndSizeX = 1.0;
- EndSizeY = 1.0;
- GravityFactor = 0.0;
- WindFactor = 0.0;
- AngleSpeed = 0.0;
- BlendMode = 0;
- Randomness = 0;
- AnimSpeed = 0.0;
- AnimCycle = 0.0;
- //Collision = false;
- //CollisionDamping = 1.0;
- Rotation = 0.0;
- CurFrame = 0.0;
- Dead = false;
- AirResistance = 1.0 / (AirResistance + 1.0);
- }
- void PxParticle::SetAirResistance(float a) { AirResistance = 1.0 / (a + 1.0); }
- void PxParticle::SetLifeTime(int t) { CurFrame = 0; LifeTime = t; }
- void PxParticle::SetStartColor(int r, int g, int b)
- { StartR = r; StartG = g; StartB = b; }
- void PxParticle::SetEndColor(int r, int g, int b)
- { EndR = r; EndG = g; EndB = b; }
- void PxParticle::SetColor(int r, int g, int b)
- { StartR = r; StartG = g; StartB = b;
- EndR = r; EndG = g; EndB = b; }
- void PxParticle::SetStartAlpha(int a) { StartA = a; }
- void PxParticle::SetEndAlpha(int a) { EndA = a; }
- void PxParticle::SetAlpha(int a) { StartA = a; EndA = a; }
- void PxParticle::SetStartSize(float x, float y) { StartSizeX = x ; StartSizeY = y; }
- void PxParticle::SetEndSize(float x, float y) { EndSizeX = x ; EndSizeY = y; }
- void PxParticle::SetSize(float x, float y) { StartSizeX = x ; StartSizeY = y;
- EndSizeX = x ; EndSizeY = y; }
- void PxParticle::GravityFactor(float g) { GravityFactor = g; }
- void PxParticle::SetWindFactor(float f) { WindFactor = f; }
- void PxParticle::SetAngleSpeed(float s) { AngleSpeed = s; }
- void PxParticle::SetVelocity(float x, float y) { SpX = x; SpY = y; }
- void PxParticle::SetBlendMode(int mode) { BlendMode = mode; }
- void PxParticle::SetMotionRandomness(float r) { Randomness = r; }
- //void PxParticle::SetWorldCollision(bool c) { Collision = c; }
- //void PxParticle::SetBounce(float d) { CollisionDamping = d; }
- void PxParticle::SetAnimSpeed(float s) { AnimSpeed = s; }
- void PxParticle::SetRandomVelocity(float min, float max)
- {
- float s = RandomFloat(min, max);
- float a = (RandomInt(0,360) * 3.141593) / 180.0;
- SpX = s * cos(a);
- SpY = s * sin(a);
- }
- void PxParticle::Draw()
- {
- if(Dead) return;
- float cycle = CurFrame / LifeTime;
- if(cycle >= 1.0) return;
- float animcycle = cycle;
- if(AnimSpeed > 0.0)
- {
- animcycle = AnimCycle;
- }
- float xsize = StartSizeX + cycle * (EndSizeX - StartSizeX);
- float ysize = StartSizeY + cycle * (EndSizeY - StartSizeY);
- float r = StartR + cycle * (EndR - StartR);
- float g = StartG + cycle * (EndG - StartG);
- float b = StartB + cycle * (EndB - StartB);
- float a = StartA + cycle * (EndA - StartA);
- int col = ARGB(a, r, g, b);
- CQuad q;
- FillSpriteQuad(&q, Sprite, animcycle, 0);
- TransformQuad(&q, Rotation, xsize, ysize, PosX, PosY);
- q.blend = BlendMode;
- for(int i=0 ; i<4 ; i+=1) q.v[i].color = col;
- RenderQuad(&q, 0);
- }
- void PxParticle::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Dead) return;
- if(Type == M_FRAME)
- {
- if(CurFrame >= LifeTime)
- {
- Randomness = 0;
- Dead = true;
- return;
- }
- Rotation += AngleSpeed;
- while(Rotation > 3.141593) Rotation -= 6.283186;
- while(Rotation <= 0 - 3.141593) Rotation += 6.283186;
- PosX = PosX + SpX;
- PosY = PosY + SpY;
- SpX = (SpX * AirResistance) + (WindFactor * Env->Wind);
- SpY = (SpY * AirResistance) + (GravityFactor * Env->Gravity);
- if(Randomness > 0)
- {
- float s = RandomFloat(0, Randomness);
- float a = (RandomInt(0,360) * 3.141593) / 180.0;
- SpX = SpX + s * cos(a);
- SpY = SpY + s * sin(a);
- }
- CurFrame += 1.0;
- if(AnimSpeed > 0.0)
- {
- AnimCycle = AnimCycle + AnimSpeed;
- if(AnimCycle >= 1.0) AnimCycle -= 1.0;
- }
- }
- }
- PXS : Library Code :
- PxAirstrikeParams::PxAirstrikeParams()
- {
- Sprite = 86;
- Sound = 52;
- NumBombs = 5;
- BombDistance = 32;
- FramesBetweenBombs = 1;
- BombSpX = 0;
- BombSpY = 0;
- SpeedCompensation = 3.0;
- PlaneAppearXOffset = 512;
- PlaneAppearYOffset = -128;
- }
- ///////////////////////////////////////////////////
- // PxAirstrike
- PxAirstrike : CObject;
- PxAirstrike::PxAirstrike(CObject* Parent, CShootDesc* Desc, PxAirstrikeParams* Params)
- {
- super(Parent, GS);
- ClType = OC_AirStrike;
- Sprite = Params->Sprite;
- Sound = Params->Sound;
- ShouldPlaySound = true;
- //Direction = Params->Direction;
- Direction = Desc->SpX;
- Team = Desc->Team;
- Worm = Desc->Worm;
- NumBombs = Params->NumBombs;
- BombDistance = Params->BombDistance;
- FramesBetweenBombs = Params->FramesBetweenBombs;
- PlaneAppearXOffset = Params->PlaneAppearXOffset;
- PlaneAppearYOffset = Params->PlaneAppearYOffset;
- SpeedCompensation = Params->SpeedCompensation;
- BombSpX = Params->BombSpX;
- BombSpY = Params->BombSpY;
- PosX = 0.0;
- PosY = 0.0;
- SpY = 0.0;
- BombDrop = 0;
- if(Direction >= 0)
- {
- // Left to right
- Direction = 1;
- SpX = BombDistance / FramesBetweenBombs;
- }
- else
- {
- // Right to left
- Direction = -1;
- SpX = -BombDistance / FramesBetweenBombs;
- BombSpX = -BombSpX;
- }
- // Position the airplane on the horizontal axis
- PosX = Desc->AddX;
- PosY = PlaneAppearYOffset;
- // Speed compensation for directional strikes depending on AddY
- int DiffY = Desc->AddY - PosY;
- if(DiffY < 0) DiffY = 0;
- float fPosX = SpeedCompensation * BombSpX * sqrt(DiffY);
- fPosX = PosX - fPosX;
- PosX = fPosX;
- BombDrop = NumBombs / 2;
- if(BombDrop * 2 == NumBombs)
- {
- // Even number of bombs
- PosX = PosX - (Direction * BombDistance) / 2;
- }
- else
- {
- // Odd number of bombs
- BombDrop = BombDrop + 1;
- }
- if(Direction == 1)
- {
- while(PosX > 0 - PlaneAppearXOffset)
- {
- PosX = PosX - FramesBetweenBombs * BombDistance;
- BombDrop = BombDrop - 1;
- }
- }
- else
- {
- while(PosX < GS->LevelSX + PlaneAppearXOffset)
- {
- PosX = PosX + FramesBetweenBombs * BombDistance;
- BombDrop = BombDrop - 1;
- }
- }
- FrameCounter = 0;
- }
- void PxAirstrike::DropBomb()
- {
- }
- void PxAirstrike::RenderPlane()
- {
- if(Direction > 0)
- {
- AddSprite(10, PosX, PosY, 0, 262144 + Sprite, 0);
- }
- else
- {
- AddSprite(10, PosX, PosY, 0, Sprite, 0);
- }
- }
- void PxAirstrike::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- // Drawing operations are done here
- if(Type == M_DRAWQUEUE)
- {
- RenderPlane();
- return;
- }
- super;
- // This is run every frame
- if(Type == M_FRAME)
- {
- if(ShouldPlaySound)
- {
- ShouldPlaySound = false;
- PlaySound(Sound, 1, 1, 0);
- }
- FrameCounter = FrameCounter + 1;
- if(FrameCounter >= FramesBetweenBombs)
- {
- FrameCounter = 0;
- if(BombDrop > 0 && BombDrop <= NumBombs)
- {
- DropBomb();
- }
- BombDrop = BombDrop + 1;
- }
- PosX = PosX + SpX;
- PosY = PosY + SpY;
- if(Direction > 0 && PosX > GS->LevelSX + PlaneAppearXOffset)
- {
- Free(true);
- }
- else if(Direction < 0 && PosX < 0 - PlaneAppearXOffset)
- {
- Free(true);
- }
- }
- }
- PXS : Library Code :
- require utils, pxparticles;
- #WEAPON_BOWLINGBALL
- CColMask* MASK_CIRCLE;
- CSprite* bowlingballSprite;
- CSprite* bowlingballsparkSprite;
- CSprite* bowlingballglowSprite;
- CLogFile* blog;
- void bowlingball::FirstFrame()
- {
- MASK_CIRCLE = new CColMask(16, 16, MakeCircleMask(16));
- }
- // Loading resources
- void bowlingball::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("bowling.png"); bowlingballSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("bowlingspark.png"); bowlingballsparkSprite = LoadSprite(f, 10, 0);
- f = GetAttachment("lightning_glow.png"); bowlingballglowSprite = LoadSprite(f, 1, 0);
- blog = new CLogFile("blog.txt");
- }
- CBowlingBall : CMine;
- CBowlingBall::CBowlingBall(CObject* Parent, CShootDesc* Desc)
- {
- CMineParams MParams;
- zero(&MParams);
- MParams.Prefuse = 0;
- MParams.Radius = 0;
- MParams.Fuse = 70;
- MParams.Flags = 0;
- MParams.Bias = 0;
- MParams.Damage = 0;
- MParams.BlastPower = 0;
- SetLayerOverride(LAYER_OILDRUM);
- super(Parent, &MParams, Desc, false, 0);
- //Layer = LAYER_OILDRUM;
- ColGroup = CMASK_SKIMMING;
- //BounceColMask = MASK_CIRCLE_SMALL;
- //BounceColMask2 = ColMask;
- BounceColMask = ColMask;
- // BounceColMask = MASK_CIRCLE;
- BounceColMask2 = MASK_PIXEL;
- ColMask = MASK_CIRCLE;
- // How much the physics object should bounce when colliding
- PhysBounciness = 0.03;
- // How much speed should be decreased when colliding
- PhysFriction = 0.02;
- // How much acceleration should be added on the X and Y axis
- PhysInertiaX = 0.8;
- PhysInertiaY = 0.4;
- // The object will be put into "low speed" state when its speed goes below this value for a long time
- LowSpeedThreshold = 4.0;
- // How many frames the physics object should hold a low speed to be put into "low speed" state
- TimeForLowSpeed = 100;
- // Regular physics parameters will be replaced by those ones when in "low speed" state
- LowSpeedBounciness = 0.03;
- LowSpeedFriction = 0.03;
- LowSpeedInertiaX = 0.0;
- LowSpeedInertiaY = 0.0;
- // Special physics parameters applied when the ball is in "electrified" state
- ZappedBounciness = 0.03;
- ZappedFriction = -0.05;
- ZappedInertiaX = 0.8;
- ZappedInertiaY = 0.4;
- SleepDistanceThreshold = 2;
- SleepSamplePeriod = 80;
- // Multiplier for incoming force from guns and melee
- GunForceMultiplier = 0.7;
- // Multiplier for incoming force from explosions
- ExplosionForceMultiplier = 1.0;
- // The minimum velocity for the ball to start emitting flame effects after being thrown by an explosion
- SpeedFlamesStartThreshold = 12.0;
- // If the ball goes below this speed for such an amount of time, it will stop emitting flames
- SpeedFlamesStopThreshold = 5.0;
- SpeedFlamesStopDuration = 100;
- SpeedFlamesStopTimer = 100;
- SpeedFlames = false;
- ThrownByExplosionTimeout = 20;
- ThrownByExplosionTimer = 0;
- ThrownByExplosion = false;
- DefaultColGroup = CMASK_TERRAIN | CMASK_WORM_ON_TERRAIN | CMASK_WORM_FROZEN |
- CMASK_CRATE | CMASK_DONORCARD | CMASK_OILDRUM;
- NoWormsColGroup = CMASK_TERRAIN | CMASK_CRATE | CMASK_DONORCARD | CMASK_OILDRUM;
- DamageableColGroup = CMASK_WORM_ON_TERRAIN | CMASK_WORM_USING_WEAPON | CMASK_WORM_IN_MIDAIR |
- CMASK_WORM_ON_ROPE | CMASK_WORM_FROZEN | CMASK_MINE |
- CMASK_CRATE | CMASK_DONORCARD | CMASK_OILDRUM;
- NextDie = GS->Tick + 500;
- Wtfboom = false;
- LastSpX = SpX;
- LastSpY = SpY;
- LastPosX = PosX;
- LastPosY = PosY;
- RealSpX = 0.0;
- RealSpY = 0.0;
- Rotation = 0.0;
- SpinMultiplierX = 0.06;
- SpinMultiplierY = 0.02;
- MaxSpinSpeed = 0.6;
- MinPushSpeed = 4.0;
- MinDamageSpeed = 4.0;
- MaxDamageSpeed = 15.0;
- DamageForceMultiplier = 0.7;
- MinDamage = 5.0;
- MaxDamage = 60.0;
- Res = new CTraceRes;
- First = true;
- EnteredSolid = false;
- LastRecordPosX = PosX;
- LastRecordPosY = PosY;
- SleepSampleTimer = 200;
- LowSpeedTimer = 200;
- IsAsleep = false;
- IsLowSpeed = false;
- //float r = GS->GetRandom()%1000;
- ZPlane = 5;
- ShakeAmplitude = 0.0;
- ShakeFadeRate = 0.2;
- //ZPlane = ZPlane + (r * 0.001);
- NextRecalcZPlane = 0;
- ClType = EObjectClass(71);
- SparkAnimSpeed = 0.02;
- SparkPauseDuration = 0.4;
- SparkCycle = 0.0;
- SparkCycleDuration = 1.0 + SparkPauseDuration;
- ZapTurnsRemaining = 0;
- GlowSize = 0.0;
- }
- void CBowlingBall::Free(bool b)
- {
- delete Res;
- super;
- }
- void CBowlingBall::Collide(CGObject* Obj, int type)
- {
- }
- void CBowlingBall::Zap(int zaptype)
- {
- float mul;
- if(zaptype == 0)
- {
- ZapTurnsRemaining = 1;
- mul = 1.0;
- }
- else
- {
- mul = 0.8;
- }
- Wake();
- float ang = RandomFloat(-0.1, 0.1);
- float speed = RandomFloat(5.0, 10.0);
- SpX = sin(ang) * speed * mul;
- SpY = -cos(ang) * speed * mul;
- }
- void CBowlingBall::DoAnimation()
- {
- if(ZapTurnsRemaining > 0)
- {
- SparkCycle = SparkCycle + SparkAnimSpeed;
- if(SparkCycle > SparkCycleDuration) SparkCycle = SparkCycle - SparkCycleDuration;
- }
- }
- void CBowlingBall::UpdateZPlane()
- {
- // Recalculate Z plane periodically to make sure objects are drawn properly when overlapping each other
- if(NextRecalcZPlane <= 0)
- {
- local matches = 0;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj == this) continue;
- if(obj->ClType == EObjectClass(71))
- {
- local ball = CBowlingBall(obj);
- float dX = ball->PosX - PosX;
- float dY = ball->PosY - PosY;
- float r2 = dX*dX + dY*dY;
- if(r2 < 900.0)
- {
- if(ball->ZPlane == ZPlane)
- {
- ball->ZPlane = ball->ZPlane + 1;
- }
- matches = matches + 1;
- }
- }
- }
- if(matches == 0) ZPlane = 5;
- NextRecalcZPlane = 200;
- }
- else
- {
- NextRecalcZPlane = NextRecalcZPlane - 1;
- }
- }
- void CBowlingBall::UpdateRotation()
- {
- float abs_speedX = RealSpX;
- float abs_speedY = RealSpY;
- if(abs_speedX < 0) abs_speedX = 0-abs_speedX;
- if(abs_speedY < 0) abs_speedY = 0-abs_speedY;
- float rot = SpinMultiplierX * abs_speedX + SpinMultiplierY * abs_speedY;
- if(rot > MaxSpinSpeed) rot = MaxSpinSpeed;
- if(RealSpX<0) rot = 0-rot;
- ApplyRotation(rot);
- }
- void CBowlingBall::ApplyRotation(float r)
- {
- Rotation += r;
- while(Rotation > 3.141593) Rotation -= 6.283186;
- while(Rotation <= 0 - 3.141593) Rotation += 6.283186;
- }
- void CBowlingBall::TakeExplosionDamage(fixed x, fixed y, int dmg)
- {
- if(dmg == 0) return;
- float fdmg = dmg;
- float dx = PosX - x;
- float dy = PosY - y;
- float distsqr = dx*dx + dy*dy;
- float fdmgsqr = fdmg*fdmg*1.25*1.25;
- fdmg = (1.0-distsqr/fdmgsqr) * fdmg;
- dmg = fdmg;
- if(dmg > 0) TakeDamage(0, dmg);
- }
- void CBowlingBall::TakeDamage(int type, int dmg)
- {
- //if(type == 10)
- //{
- // fixed fdmg = dmg;
- // fdmg = Health * fdmg / 100.0;
- // dmg = fdmg;
- //}
- //Health -= dmg;
- Wake();
- }
- void CBowlingBall::Sleep()
- {
- if(IsAsleep) return;
- IsAsleep = true;
- IsLowSpeed = false;
- //IsMaterial = true;
- SleepX = PosX;
- SleepY = PosY;
- SpeedDivider = 1000;
- SpeedDividerB = 1000;
- SpX = 0.0;
- SpY = 0.0;
- GravityFactor = 0.0;
- Stopped = 1;
- InMidAir = 0;
- ThrownByExplosion = false;
- SpeedFlames = false;
- }
- void CBowlingBall::Wake()
- {
- if(IsAsleep == false && IsLowSpeed == false) return;
- IsAsleep = false;
- IsLowSpeed = false;
- //IsMaterial = false;
- SleepX = 0;
- SleepY = 0;
- SpeedDivider = 1;
- SpeedDividerB = 1;
- GravityFactor = 1.0;
- Stopped = 0;
- InMidAir = 1;
- SleepSampleTimer = 200;
- LowSpeedTimer = 200;
- }
- void CBowlingBall::Render()
- {
- bool hascolormod = false;
- if(Sinking)
- {
- hascolormod = true;
- SetColorMod(RGB(90, 90, 240), 6);
- }
- //else if(IsAsleep)
- //{
- // hascolormod = true;
- // SetColorMod(RGB(0, 255, 0), 6);
- //}
- //else if(IsLowSpeed)
- //{
- // hascolormod = true;
- // SetColorMod(RGB(255, 180, 0), 6);
- //}
- AddSpriteEx(ZPlane+0.01, PosX, PosY, bowlingballSprite->Index, 0, Rotation, 1);
- if(hascolormod) ClearColorMod();
- if(Sinking == false && ZapTurnsRemaining > 0)
- {
- CQuad q;
- int j;
- // Glow effect
- FillSpriteQuad(&q, bowlingballglowSprite->Index, 0, 0);
- TransformQuad(&q, 0, GlowSize, GlowSize, PosX, PosY);
- q.blend = 1;
- for(j=0 ; j<4 ; j+=1) q.v[j].color = RGB(80,110,128);
- for(j=0 ; j<3 ; j+=1)
- AddSpriteQ(ZPlane+0.02, &q, bowlingballglowSprite->Index, 0, 64);
- if(SparkCycle <= 1.0)
- {
- // Spark effect
- FillSpriteQuad(&q, bowlingballsparkSprite->Index, 0, 0);
- TransformQuad(&q, Rotation, 1, 1, PosX, PosY);
- q.blend = 1;
- for(j=0 ; j<4 ; j+=1) q.v[j].color = RGB(255,255,255);
- AddSpriteQ(ZPlane, &q, bowlingballsparkSprite->Index, SparkCycle, 64);
- }
- }
- if(EnteredSolid)
- {
- AddSpriteEx(9, PosX, PosY, 2, 0, 0, 1);
- }
- }
- void CBowlingBall::ProcessBallOnBallCollision(float Speed)
- {
- CGObject *obj;
- for(int i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == this) continue;
- if(obj == NullObj) continue;
- if(obj->ClType == ClType)
- {
- if(ColMask->Check(PosX, PosY, obj->ColMask, obj->PosX, obj->PosY))
- {
- float ForceX = obj->PosX - PosX;
- float ForceY = obj->PosY - PosY;
- float dist = sqrt(ForceX*ForceX + ForceY*ForceY);
- if(dist > 0)
- {
- ForceX = 0.6*sqrt(Speed) * ForceX / dist;
- ForceY = 0.6*sqrt(Speed) * ForceY / dist;
- CMessageData msg;
- msg.params[0] = 0;
- msg.fparams[1] = PosX;
- msg.fparams[2] = PosY;
- msg.fparams[3] = ForceX;
- msg.fparams[4] = ForceY;
- msg.params[5] = 1;
- msg.params[6] = 0;
- obj->Message(this, M_GUNEXP, 1032, &msg);
- }
- }
- }
- }
- }
- void CBowlingBall::ProcessBallOnOtherCollision(float Speed)
- {
- CGObject *obj;
- float dmg = Speed;
- if(dmg>MaxDamageSpeed) dmg = MaxDamageSpeed;
- dmg = MinDamage + (MaxDamage - MinDamage) * (dmg - MinDamageSpeed) / (MaxDamageSpeed - MinDamageSpeed);
- for(int i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == this) continue;
- if(obj == NullObj) continue;
- if(obj->IsMaterial == false) continue;
- if(ColMask->Check(PosX, PosY, obj->ColMask, obj->PosX, obj->PosY))
- {
- blog->Write("AAAD3");
- float damage = 0;
- if(obj->ClType == OC_Worm)
- {
- local worm = CWorm(obj);
- if(worm->DamageRecoverTime <= 0)
- {
- if(obj->ObjState == WS_IDLE) damage = dmg;
- if(obj->ObjState == WS_SLIDING) damage = dmg;
- if(obj->ObjState == WS_WALKING) damage = dmg;
- if(obj->ObjState == WS_AIMING) damage = dmg;
- if(obj->ObjState == WS_FIRED) damage = dmg;
- if(obj->ObjState == WS_FIRECONT) damage = dmg;
- if(obj->ObjState == WS_DRILLING) damage = dmg;
- if(obj->ObjState == WS_CONTROL_WEAPON) damage = dmg;
- if(obj->ObjState == WS_SETPOWER) damage = dmg;
- if(obj->ObjState == WS_JUMPPREPARE) damage = dmg;
- if(obj->ObjState == WS_FROZEN) damage = dmg;
- if(obj->ObjState == WS_POWERFLY) damage = dmg;
- if(obj->ObjState == WS_FLYING) damage = dmg;
- if(obj->ObjState == WS_FLYING2) damage = dmg;
- if(obj->ObjState == WS_FLYING2) damage = dmg;
- if(obj->ObjState == WS_JETPACK) damage = dmg;
- if(obj->ObjState == WS_PARACHUTE) damage = dmg;
- if(obj->ObjState == WS_JUMP) damage = dmg;
- if(obj->ObjState == WS_ROPING) damage = dmg;
- if(obj->ObjState == WS_BUNGEE) damage = dmg;
- worm->DamageRecoverTime = 12;
- }
- }
- else if(obj->ClType == OC_Mine)
- {
- damage = dmg;
- }
- else if(obj is CMagnet)
- {
- damage = dmg;
- }
- else if(obj->ClType == EObjectClass(73))
- {
- damage = dmg;
- }
- else if(obj->ClType == OC_OilDrum)
- {
- damage = 100;
- }
- else if(obj->ClType == OC_Crate)
- {
- damage = 100;
- }
- if(damage > 0)
- {
- float ForceX = RealSpX;
- float ForceY = RealSpY;
- float ForceXAbs = ForceX;
- bool crushed = false;
- if(ForceX < 0) ForceXAbs = 0-ForceXAbs;
- if(obj->ClType == OC_Worm)
- {
- bool crushable = false;
- if(obj->ObjState == WS_IDLE) crushable = true;
- if(obj->ObjState == WS_WALKING) crushable = true;
- if(obj->ObjState == WS_AIMING) crushable = true;
- if(obj->ObjState == WS_FIRED) crushable = true;
- if(obj->ObjState == WS_FIRECONT) crushable = true;
- if(obj->ObjState == WS_CONTROL_WEAPON) crushable = true;
- if(obj->ObjState == WS_SETPOWER) crushable = true;
- if(obj->ObjState == WS_JUMPPREPARE) crushable = true;
- if(crushable && ForceY > MinDamageSpeed)
- {
- if(ForceXAbs / ForceY < 0.2)
- {
- ForceX = 0;
- ForceY = 10;
- crushed = true;
- }
- }
- }
- if(crushed==false)
- {
- if(ForceY < 0)
- {
- ForceY = ForceY - ForceXAbs;
- }
- else
- {
- ForceY = ForceY - 2*ForceXAbs;
- }
- ForceX = ForceX * DamageForceMultiplier;
- ForceY = ForceY * DamageForceMultiplier;
- }
- CMessageData msg;
- msg.params[0] = 0;
- msg.fparams[1] = PosX;
- msg.fparams[2] = PosY;
- msg.fparams[3] = ForceX;
- msg.fparams[4] = ForceY;
- msg.params[5] = damage;
- msg.params[6] = 0;
- obj->Message(this, M_GUNEXP, 1032, &msg);
- local p = new PxParticle(81, PosX, PosY);
- p->SetLifeTime(15);
- p->SetVelocity(0,0);
- p->SetStartAlpha(255);
- p->SetEndAlpha(255);
- if(crushed)
- {
- PlayLocalSound(33, 5, 1.0, 1.0);
- }
- else
- {
- PlayLocalSound(101, 5, 1.0, 1.0);
- }
- }
- }
- }
- }
- void CBowlingBall::PhysicsThink()
- {
- if(IsAsleep)
- {
- PosX = SleepX;
- PosY = SleepY;
- RealSpX = 0.0;
- RealSpY = 0.0;
- SpX = 0.0;
- SpY = 0.0;
- Stopped = 1;
- InMidAir = 0;
- }
- else
- {
- float Speed = sqrt(RealSpX*RealSpX + RealSpY*RealSpY);
- fixed SpX2 = SpX;
- fixed SpY2 = SpY + Env->Gravity;
- float bounciness;
- float friction;
- float inertiaX;
- float inertiaY;
- if(IsLowSpeed)
- {
- bounciness = LowSpeedBounciness;
- friction = LowSpeedFriction;
- inertiaX = LowSpeedInertiaX;
- inertiaY = LowSpeedInertiaY;
- }
- else if(ZapTurnsRemaining > 0)
- {
- bounciness = ZappedBounciness;
- friction = ZappedFriction;
- inertiaX = ZappedInertiaX;
- inertiaY = ZappedInertiaY;
- }
- else
- {
- bounciness = PhysBounciness;
- friction = PhysFriction;
- inertiaX = PhysInertiaX;
- inertiaY = PhysInertiaY;
- }
- if(SpX2 == 0)
- {
- if(SpY2 == 0)
- {
- SpY2 = SpY + 0.1;
- }
- }
- // Collision detection
- if(Speed > MinDamageSpeed)
- {
- // Enough speed for knocking stuff out of the way, ignore worms
- TraceMaskEx(this, BounceColMask, PosX, PosY, PosX + SpX2, PosY + SpY2, NoWormsColGroup, Res);
- }
- else
- {
- // Regular traces, takes anything solid into consideration
- TraceMaskEx(this, BounceColMask, PosX, PosY, PosX + SpX2, PosY + SpY2, DefaultColGroup, Res);
- }
- if(Res->StartsSolid)
- {
- TraceMaskEx(this, BounceColMask, PosX, PosY, PosX + SpX2, PosY + SpY2, NoWormsColGroup, Res);
- if(Res->StartsSolid)
- {
- // The object is stuck inside something solid, try to unblock it
- TraceMaskEx(this, BounceColMask, PosX, PosY, PosX - 8 * SpX2, PosY - 8 * SpY2, NoWormsColGroup, Res);
- TraceMaskEx(this, BounceColMask, Res->LeftSolidX, Res->LeftSolidY, Res->LeftSolidX + 8 * SpX2, Res->LeftSolidY + 8 * SpY2, NoWormsColGroup, Res);
- }
- }
- // Couldn't unblock it :(
- if(Res->StartsSolid)
- {
- TraceMaskEx(this, BounceColMask2, PosX, PosY, PosX - 8 * SpX2, PosY - 8 * SpY2, NoWormsColGroup, Res);
- TraceMaskEx(this, BounceColMask2, Res->LeftSolidX, Res->LeftSolidY, Res->LeftSolidX + 8 * SpX2, Res->LeftSolidY + 8 * SpY2, NoWormsColGroup, Res);
- if(Res->StartsSolid)
- {
- //EnteredSolid = true;
- //SpY = SpY - 4.0;
- Sleep();
- }
- }
- // Collision processing
- if(Res->Hit)
- {
- First = false;
- // Calculating tangent and normal initial forces
- float SpT = (SpX2 * Res->TangentX) + (SpY2 * Res->TangentY);
- float SpN = (SpX2 * Res->NormalX ) + (SpY2 * Res->NormalY );
- // Move the object 1 pixel away from the collision point
- PosX = Res->PreHitX;
- PosY = Res->PreHitY;
- // Calculating bounciness and friction forces
- float ForceX = 0 - SpN * Res->NormalX * (bounciness + 1.0) - SpT * Res->TangentX * friction;
- float ForceY = 0 - SpN * Res->NormalY * (bounciness + 1.0) - SpT * Res->TangentY * friction;
- // Calculating work of the resulting force relative to the current speed
- float W = (ForceX * SpX2) + (ForceY * SpY2);
- if(W < -10.0)
- {
- // Negative work, the object has been brutally stopped, shake the screen to give more intensity to the impact
- float shake = 0 - W;
- if(shake > 50.0) shake = 50.0;
- shake = shake * 0.1;
- if(shake > ShakeAmplitude)
- {
- GS->ShakeX = GS->ShakeX + (shake - ShakeAmplitude);
- GS->ShakeY = GS->ShakeY + (shake - ShakeAmplitude);
- ShakeAmplitude = shake;
- }
- }
- SpX = SpX + ForceX;
- SpY = SpY + ForceY;
- float sp = Speed;
- if(sp > 1.5)
- {
- for(int i=0 ; i<4 ; i+=1)
- {
- local p = new PxParticle(80, PosX, PosY);
- p->SetLifeTime(30);
- p->SetRandomVelocity(sp*0.5, sp*1.2);
- p->SetAirResistance(0.5);
- p->SetStartAlpha(255);
- p->SetEndAlpha(255);
- }
- }
- }
- SpX = SpX + inertiaX * (SpX - LastSpX);
- SpY = SpY + inertiaY * (SpY - LastSpY);
- RealSpX = PosX - LastPosX;
- RealSpY = PosY - LastPosY;
- // Should solve an issue where the object keeps rolling on a perfectly horizontal surface,
- // even though friction should prevent it from doing so
- if(IsLowSpeed)
- {
- if(RealSpY > -1.0)
- {
- if(RealSpY < 1.0)
- {
- if(SpX > -1.0)
- {
- if(SpX < 0.0) SpX = 0;
- }
- }
- }
- }
- LastPosX = PosX;
- LastPosY = PosY;
- LastSpX = SpX;
- LastSpY = SpY;
- if(ThrownByExplosion)
- {
- if(SpeedFlames)
- {
- if(Speed < SpeedFlamesStopThreshold)
- {
- SpeedFlamesStopTimer = SpeedFlamesStopTimer - 1;
- if(SpeedFlamesStopTimer <= 0)
- {
- SpeedFlames = false;
- }
- }
- else
- {
- SpeedFlamesStopTimer = SpeedFlamesStopDuration;
- }
- }
- else
- {
- if(Speed > SpeedFlamesStartThreshold)
- {
- SpeedFlamesStopTimer = SpeedFlamesStopDuration;
- SpeedFlames = true;
- }
- ThrownByExplosionTimer = ThrownByExplosionTimer - 1;
- if(ThrownByExplosionTimer <= 0)
- {
- ThrownByExplosion = false;
- }
- }
- }
- if(Speed > MinPushSpeed)
- {
- ProcessBallOnBallCollision(Speed);
- }
- if(Speed > MinDamageSpeed)
- {
- ProcessBallOnOtherCollision(Speed);
- }
- if(Speed < LowSpeedThreshold)
- {
- LowSpeedTimer = LowSpeedTimer - 1;
- if(LowSpeedTimer <= 0)
- {
- //local p = new PxParticle(81, PosX, PosY);
- //p->SetLifeTime(30);
- //p->SetVelocity(0,0);
- //p->SetStartAlpha(255);
- //p->SetEndAlpha(255);
- IsLowSpeed = true;
- LowSpeedTimer = TimeForLowSpeed;
- }
- }
- else
- {
- LowSpeedTimer = TimeForLowSpeed;
- IsLowSpeed = false;
- }
- SleepSampleTimer = SleepSampleTimer - 1;
- if(SleepSampleTimer <= 0)
- {
- //local p = new PxParticle(79, PosX, PosY);
- //p->SetLifeTime(30);
- //p->SetVelocity(0,0);
- //p->SetStartAlpha(255);
- //p->SetEndAlpha(255);
- float dx = PosX - LastRecordPosX;
- float dy = PosY - LastRecordPosY;
- float dist = sqrt(dx*dx+dy*dy);
- if(dist < SleepDistanceThreshold) Sleep();
- SleepSampleTimer = SleepSamplePeriod;
- LastRecordPosX = PosX;
- LastRecordPosY = PosY;
- }
- }
- }
- void CBowlingBall::DoTrailEffects()
- {
- local p0 = PxParticle(NullObj);
- float s0;
- float s1;
- if(IsAsleep == false && IsLowSpeed == false)
- {
- // Regular trail
- p0 = new PxParticle(bowlingballglowSprite->Index, PosX, PosY);
- p0->SetBlendMode(1);
- p0->SetStartColor(45,10,4);
- p0->SetEndColor(0,0,0);
- p0->SetLifeTime(15);
- p0->SetRandomVelocity(0, 0);
- p0->SetAirResistance(0);
- p0->SetAlpha(255);
- p0->SetStartSize(0.3,0.3);
- p0->SetEndSize(0.35,0.35);
- }
- // Electrified ball
- GlowSize = RandomFloat(0.5, 0.9);
- if(ZapTurnsRemaining > 0 && (IsAsleep == false))
- {
- s0 = RandomFloat(0.2,0.3);
- s1 = RandomFloat(0.4,0.5);
- p0 = new PxParticle(bowlingballglowSprite->Index, PosX, PosY);
- p0->SetBlendMode(1);
- p0->SetStartColor(80,110,128);
- p0->SetEndColor(0,0,0);
- p0->SetLifeTime(30);
- p0->SetRandomVelocity(0, 0.3);
- p0->SetAirResistance(0.0);
- p0->SetAlpha(255);
- p0->SetStartSize(0.3,0.3);
- p0->SetEndSize(0.5,0.5);
- }
- // Fire trail when the ball is thrown by an explosion
- else if(ThrownByExplosion && (IsAsleep == false))
- {
- if(SpeedFlames)
- {
- s0 = RandomFloat(0.1, 0.2);
- s1 = RandomFloat(0.05, 0.1);
- p0 = new PxParticle(bowlingballglowSprite->Index, PosX, PosY);
- p0->SetBlendMode(1);
- p0->SetStartColor(160,RandomInt(30,160),10);
- p0->SetEndColor(0,0,0);
- p0->SetLifeTime(20);
- p0->SetRandomVelocity(0, 0.3);
- p0->SetAirResistance(0);
- p0->SetAlpha(255);
- p0->SetStartSize(s0,s0);
- p0->SetEndSize(s1,s1);
- }
- }
- }
- void CBowlingBall::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Wtfboom) return;
- if(Type == M_EXPLOSION)
- {
- TakeExplosionDamage(MData->fparams[1], MData->fparams[2], MData->params[4]);
- ThrownByExplosion = true;
- ThrownByExplosionTimer = ThrownByExplosionTimeout;
- float force = MData->params[3];
- force = force * ExplosionForceMultiplier;
- MData->params[3] = force;
- }
- if(Type == M_GUNEXP)
- {
- TakeDamage(MData->params[0], MData->params[5]);
- MData->params[3] = MData->params[3] * GunForceMultiplier;
- MData->params[4] = MData->params[4] * GunForceMultiplier;
- }
- if(Type==M_FRAME)
- {
- if(ShakeAmplitude > 0)
- {
- ShakeAmplitude = ShakeAmplitude - ShakeFadeRate; if(ShakeAmplitude < 0) ShakeAmplitude = 0;
- GS->ShakeX = GS->ShakeX - ShakeFadeRate; if(GS->ShakeX < 0) GS->ShakeX = 0;
- GS->ShakeY = GS->ShakeY - ShakeFadeRate; if(GS->ShakeY < 0) GS->ShakeY = 0;
- }
- if(Sinking==false)
- {
- DoAnimation();
- UpdateRotation();
- PhysicsThink();
- DoTrailEffects();
- }
- }
- if(Type==M_DRAWQUEUE)
- {
- Render();
- return;
- }
- super;
- if(Type == M_FRAME)
- {
- if(Wtfboom) Free(true);
- }
- }
- override CWorm::CWorm(CObject* Parent, int aTeam, int aIndex, CWormParams* params)
- {
- super;
- DamageRecoverTime = 0;
- }
- override void CWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if(DamageRecoverTime > 0) DamageRecoverTime = DamageRecoverTime - 1;
- }
- super;
- }
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Bowling Ball"))
- {
- CShootDesc SDesc;
- zero(&SDesc);
- local BaseForceX = 0.4;
- local BaseForceY = 0.8;
- SDesc.Team = WormTeam;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = (0.5 * SpX) + TurnSide * BaseForceX;
- SDesc.SpY = (0.5 * SpY) - BaseForceY;
- DamageRecoverTime = 50;
- new CBowlingBall(GetObject(25, 0), &SDesc);
- }
- else if(Weap->CheckName("Earth Quake"))
- {
- CGObject *obj;
- CBowlingBall *ball;
- for(int i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == NullObj) continue;
- if(obj->ClType == EObjectClass(71))
- {
- ball = CBowlingBall(obj);
- ball->Wake();
- }
- }
- super;
- }
- else
- {
- super;
- }
- }
- PXS : Library Code :
- require pxairstrike;
- PxAirstrikeParams *BowlingBallStrikeParams;
- void bbstrike::FirstFrame()
- {
- BowlingBallStrikeParams = new PxAirstrikeParams;
- BowlingBallStrikeParams->SpeedCompensation = 2.5;
- }
- ///////////////////////////////////////////////////
- // PxBowlingBallStrike
- PxBowlingBallStrike : PxAirstrike
- PxBowlingBallStrike::PxBowlingBallStrike(CObject* Parent, CShootDesc* Desc, PxAirstrikeParams* Params)
- {
- super;
- }
- void PxBowlingBallStrike::DropBomb()
- {
- CShootDesc SDesc;
- zero(&SDesc);
- SDesc.Team = Team;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = BombSpX;
- SDesc.SpY = BombSpY;
- new CBowlingBall(GetObject(25, 0), &SDesc);
- }
- void PxBowlingBallStrike::RenderPlane()
- {
- super;
- }
- ///////////////////////////////////////////////////
- // CWorm overrides
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Bowling Ball Strike"))
- {
- BowlingBallStrikeParams->NumBombs = 3;
- BowlingBallStrikeParams->BombDistance = 48;
- BowlingBallStrikeParams->BombSpX = 5;
- BowlingBallStrikeParams->BombSpY = 0;
- new PxBowlingBallStrike(GetObject(25, 0), Desc, BowlingBallStrikeParams);
- }
- else
- {
- super;
- }
- }
- PXS : Library Code :
- require utils, pxparticles, wp_bowlingball;
- #WEAPON_MAGNET
- CSprite* magnetSprite;
- CSprite* magnetSprite2;
- CSprite* magnetDamagedSprite;
- CSprite* magnetDamagedSprite2;
- CSprite* magnetRingSprite;
- CSprite* magnetRingSprite2;
- CSprite* magnetSparks;
- CSprite* magmissileSprite;
- CSprite* magmissileSprite2;
- CSprite* wmaglnk;
- CSprite* wmaglnku;
- CSprite* wmaglnkd;
- CSprite* wmag2lnk;
- CSprite* wmag2lnku;
- CSprite* wmag2lnkd;
- CMagnet : CMine;
- CMagnetResult::CMagnetResult()
- {
- ForceX = float(0.0);
- ForceY = float(0.0);
- IsNull = true;
- }
- void CMagnetResult::Reset()
- {
- ForceX = float(0.0);
- ForceY = float(0.0);
- IsNull = true;
- }
- CMagnetResult *MagnetInternalResult;
- //CBitmap32* AnimDebugBitmap;
- //string AnimDebugText;
- // Loading resources
- void magnet::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("magnet.png"); magnetSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("magnet2.png"); magnetSprite2 = LoadSprite(f, 1, 0);
- f = GetAttachment("magnet_damaged.png"); magnetDamagedSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("magnet2_damaged.png"); magnetDamagedSprite2 = LoadSprite(f, 1, 0);
- f = GetAttachment("ring_in.png"); magnetRingSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("ring_out.png"); magnetRingSprite2 = LoadSprite(f, 1, 0);
- f = GetAttachment("magnetsparks.png"); magnetSparks = LoadSprite(f, 10, 0);
- f = GetAttachment("magmissile.png"); magmissileSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("magmissile2.png"); magmissileSprite2 = LoadSprite(f, 1, 0);
- // note to entuser and self: the third parameter isn't actually flags, it's the framerate of the sprite
- // also those deploy animation sprites need to be loaded in a precise order (normal, up, down)
- f = GetAttachment("wmaglnk.png"); wmaglnk = LoadSprite(f, 10, 24);
- f = GetAttachment("wmaglnku.png"); wmaglnku = LoadSprite(f, 10, 24);
- f = GetAttachment("wmaglnkd.png"); wmaglnkd = LoadSprite(f, 10, 24);
- f = GetAttachment("wmag2lnk.png"); wmag2lnk = LoadSprite(f, 10, 24);
- f = GetAttachment("wmag2lnku.png"); wmag2lnku = LoadSprite(f, 10, 24);
- f = GetAttachment("wmag2lnkd.png"); wmag2lnkd = LoadSprite(f, 10, 24);
- //AnimDebugBitmap = MakeBitmap(300,36);
- //AnimDebugText = "geez";
- }
- void magnet::FirstFrame()
- {
- local envfilter = CFilter(Root->GetObject(25, 0));
- envfilter->Allow(M_TURNEND);
- MagnetInternalResult = new CMagnetResult();
- }
- ///////////////////////////////////////////////////
- // CMagnet class
- CMagnet::CMagnet(CObject* Parent, CShootDesc* Desc, int WormDir, int Pol)
- {
- WormTurnSide = WormDir;
- // Maximum distance in which objects can be affected by the magnet
- MaxRange = 170.0;
- // Maximum acceleration the magnet can apply
- MaxForce = 12.0;
- // How much the force applied by the magnet is multiplied
- ForceCoefficient = 14000.0;
- // This value is added to the squared distance to avoid divisions by zero, it also gives the magnet a less violent behaviour
- // on objects which are near the center
- AttractOffset = 10.0;
- RepelOffset = 5.0;
- // If set to true, magnets in attract mode will attempt to synchronize caught random mines
- // so they explode at the same time, causing maximum damage
- MineTriggerSync = true;
- // How many cycles of turns before the magnet stops working
- TurnsRemaining = 4;
- // How much damage the magnet can take before breaking
- Health = 80;
- ExplosionDamage = 50;
- ExplosionBlast = 100;
- // Ignore any damage taken
- IgnoreDamage = false;
- // Offset between the projectile and the actual magnetic field
- MagnetOffsetX = 0.0;
- MagnetOffsetY = 0.0;
- MagnetOffsetRelative = false;
- // END OF MAGNET PARAMETERS
- // Sprite parameters
- Sprite1 = magnetSprite->Index;
- Sprite2 = magnetSprite2->Index;
- Sprite1Damaged = magnetDamagedSprite->Index;
- Sprite2Damaged = magnetDamagedSprite2->Index;
- // Animation parameters
- SpinMultiplier = 0.04;
- MaxSpinSpeed = 0.5;
- OrientationOption = 0;
- RingSpeed = 8;
- RingPeriod = 65;
- RingMinSize = 5;
- RingMaxSize = 120;
- SparkAnimSpeed = 0.02;
- SparkPauseDuration = 0.4;
- // Physics crap
- DumpingA = 0.3;
- DumpingB = 0.3;
- DumpingC = 0.3;
- // Private shit
- Removed = false;
- Rotation = float(0.0);
- Mirrored = false;
- Polarity = Pol;
- LowHealth = 30;
- NumRings = 0;
- Rings = new int[5];
- for(local i=0 ; i<5 ; i+=1) Rings[i] = 0;
- NextRing = 0;
- NextRecalcZPlane = 0;
- ZPlane = 10;
- SparkCycle = 0.0;
- OwnerTeam = Desc->Team;
- LastTeam = OwnerTeam;
- CMineParams MParams;
- zero(&MParams);
- MParams.Prefuse = 0;
- MParams.Flags = 0;
- MParams.Bias = 0;
- MParams.Radius = 1;
- MParams.Fuse = 70;
- MParams.Damage = 48;
- MParams.BlastPower = 100;
- super(Parent, &MParams, Desc, false, 0);
- MagnetPosX = PosX;
- MagnetPosY = PosY;
- ClType = EObjectClass(70);
- Initialized = false;
- TurnEnded = false;
- TurnEndTime = 0;
- TurnsLifetime = 0;
- DoMagneticField(false, true);
- }
- void CMagnetResult::CalculateMagneticForce(CMagnet *mag, fixed PosX, fixed PosY, float fmul)
- {
- if(mag->Removed || mag->TurnsRemaining <= 0) return;
- float offset = mag->RepelOffset;
- if(mag->Polarity < 0)
- {
- offset = mag->AttractOffset;
- }
- // Calculating distance from object to magnet
- float fX = PosX - mag->MagnetPosX;
- float fY = PosY - mag->MagnetPosY;
- float r2 = fX*fX + fY*fY + offset;
- // Too far away, don't do anything
- if(r2>mag->MaxRange) return;
- // Calculating force
- float r = sqrt(r2);
- float mul = mag->ForceCoefficient / r2;
- if(mul > mag->MaxForce) mul = mag->MaxForce;
- fX = (fX / r) * mul * mag->Polarity;
- fY = (fY / r) * mul * mag->Polarity;
- ForceX = fmul * fX;
- ForceY = fmul * fY;
- IsNull = false;
- }
- void CMagnetResult::CalculateGlobalMagneticForce(fixed PosX, fixed PosY, float fmul)
- {
- for(int i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj is CMagnet)
- {
- CMagnet *mag = CMagnet(obj);
- CalculateMagneticForce(mag, PosX, PosY, fmul);
- }
- }
- }
- // Placeholder for CMagnetMissile
- void CMagnet::Collide(CGObject* Obj, int type)
- {
- super;
- }
- // Initializations which require the initial parameters should be done there
- void CMagnet::InitializeParameters()
- {
- if(Initialized) return;
- MaxRange = MaxRange * MaxRange;
- MaxSyncRange = MaxRange * 0.25;
- AttractOffset = AttractOffset * AttractOffset;
- RepelOffset = RepelOffset * RepelOffset;
- RingMinSize = RingMinSize * 10;
- RingMaxSize = RingMaxSize * 10;
- SparkCycleDuration = 1.0 + SparkPauseDuration;
- TurnsLifetime = TurnsRemaining;
- Initialized = true;
- }
- // Recharges a discharged magnet
- void CMagnet::Recharge()
- {
- if(Removed) return;
- if(TurnsRemaining <= 0)
- {
- NextRing = 0;
- }
- TurnsRemaining = TurnsLifetime;
- DoMagneticField(false, true);
- }
- // Update the position of the magnetic field relative to the actual projectile
- void CMagnet::UpdateMagnetPosition()
- {
- if(MagnetOffsetRelative)
- {
- float s = sin(Rotation);
- float c = cos(Rotation);
- MagnetPosX = PosX - s * MagnetOffsetX - c * MagnetOffsetY;
- MagnetPosY = PosY + c * MagnetOffsetX - s * MagnetOffsetY;
- }
- else
- {
- MagnetPosX = PosX + MagnetOffsetX;
- MagnetPosY = PosY + MagnetOffsetY;
- }
- }
- // Update the angle of the projectile
- void CMagnet::UpdateRotation()
- {
- if(OrientationOption == 0)
- {
- float speed = sqrt(SpX*SpX + SpY*SpY);
- float rot = SpinMultiplier * speed;
- if(rot > MaxSpinSpeed) rot = MaxSpinSpeed;
- if(SpX<0) rot = 0-rot;
- ApplyRotation(rot);
- }
- else
- {
- if(SpX==0.0)
- {
- if(SpY>0.0)
- {
- if(WormTurnSide > 0)
- {
- // something weird is happening HERE //no moar (ent)
- Rotation = 0;
- }
- else
- {
- Rotation = 3.141593;
- }
- }
- else if(SpY<0.0)
- {
- if(WormTurnSide > 0)
- {
- Rotation = 3.141593;
- }
- else
- {
- Rotation = 0;
- }
- }
- }
- else
- {
- Rotation = 0-atan2(SpX, SpY);
- }
- ApplyRotation(0.0);
- }
- }
- // Rotates the projectile by r radians, and normalizes the angle
- void CMagnet::ApplyRotation(float r)
- {
- Rotation += r;
- while(Rotation > 3.141593) Rotation -= 6.283186;
- while(Rotation <= 0 - 3.141593) Rotation += 6.283186;
- }
- // Applies blast damage to the magnet
- // x, y : origin of the explosion
- // dmg : maximum damage the explosion should do
- void CMagnet::TakeExplosionDamage(fixed x, fixed y, int dmg)
- {
- if(dmg == 0) return;
- float fdmg = dmg;
- float dx = PosX - x;
- float dy = PosY - y;
- float distsqr = dx*dx + dy*dy;
- float fdmgsqr = fdmg*fdmg*4.0;
- fdmg = (1.0-distsqr/fdmgsqr) * fdmg;
- dmg = fdmg;
- if(dmg > 0) TakeDamage(0, dmg);
- }
- // Applies direct damage to the magnet (without any further calculation)
- // type should be always 0 (10 is for percentage-based damage and is reserved to the Battle Axe)
- void CMagnet::TakeDamage(int type, int dmg)
- {
- if(type == 10)
- {
- fixed fdmg = dmg;
- fdmg = Health * fdmg / 100.0;
- dmg = fdmg;
- }
- Health -= dmg;
- }
- int CMagnet::GetRing(int i) { return Rings[i]; }
- void CMagnet::SetRing(int i, int x) { Rings[i] = x; }
- // Adds a ring effect to the magnetic field
- void CMagnet::PushRing()
- {
- if(NumRings<5)
- {
- if(Polarity>0) SetRing(NumRings, RingMinSize);
- else SetRing(NumRings, RingMaxSize);
- NumRings = NumRings + 1;
- }
- }
- // Removes a ring when it has disappeared
- void CMagnet::PopRing()
- {
- if(NumRings>0)
- {
- for(local i = 1; i < NumRings; i+=1)
- {
- SetRing(i-1, GetRing(i));
- }
- NumRings = NumRings - 1;
- }
- }
- // Triggers a mine and applies mine timer synchronization
- void CMagnet::TriggerMine(CMine *mine)
- {
- // Not a special mine
- if(mine->Radius > 1 && mine->Active == 0 && mine->Prefuse <= 0 && mine->Fuse < 0)
- {
- // Give it a random fuse time (between 1 and 5)
- mine->Fuse = 1000 + (GS->GetRandom()%4000);
- // Mine synchronisation mode is on
- if(MineTriggerSync)
- {
- // Only applies to magnets in attract mode
- if(Polarity<0)
- {
- // Search for an attracted mine with the highest fuse time
- int maxFuse = 1000;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj2 = Env->Objs.Objs[i];
- if(obj2 == NullObj) continue;
- if(obj2->ClType == OC_Mine)
- {
- local mine2 = CMine(obj2);
- if(mine2 == mine) continue;
- // Calculate distance from mine to magnet
- float mX = mine2->PosX - MagnetPosX;
- float mY = mine2->PosY - MagnetPosY;
- float rm2 = mX * mX + mY * mY;
- // If it's close enough, we'll consider it's being attracted
- if(rm2 < MaxSyncRange)
- {
- if(mine2->Fuse > maxFuse) maxFuse = mine2->Fuse;
- }
- }
- }
- // If another mine was found and its fuse is long enough
- if(maxFuse > 1000)
- {
- // Synchronize the current mine with it
- // and give it a slight random offset so it doesn't look too suspicious
- mine->Fuse = maxFuse + (GS->GetRandom()%400) - 200;
- }
- }
- }
- }
- // Trigger the mine
- mine->Active = 1;
- mine->nPulses = mine->Fuse / 250;
- }
- // Applies force to nearby objects
- // It will also trigger mines to make sure the turn will not get stuck due to perpetual motion
- void CMagnet::ApplyForce(CGObject *obj, float fmul, bool forceWake)
- {
- // Wake up nearby bowling balls
- if(SpX != 0 || SpY != 0) forceWake = true;
- if(forceWake == false)
- {
- if(#WEAPON_BOWLINGBALL)
- {
- if(obj is CBowlingBall)
- {
- local ball = CBowlingBall(obj);
- if(ball->IsAsleep) return;
- }
- }
- }
- MagnetInternalResult->Reset();
- MagnetInternalResult->CalculateMagneticForce(this, obj->PosX, obj->PosY, fmul);
- if(MagnetInternalResult->IsNull) return;
- // If the object is a mine, trigger it to make it explode
- if(obj->ClType == OC_Mine)
- {
- local mine = CMine(obj);
- TriggerMine(mine);
- }
- if(forceWake)
- {
- if(#WEAPON_BOWLINGBALL)
- {
- if(obj is CBowlingBall)
- {
- CBowlingBall *ball = CBowlingBall(obj);
- ball->Wake();
- }
- }
- }
- // Applying force
- obj->SpX += MagnetInternalResult->ForceX;
- obj->SpY += MagnetInternalResult->ForceY;
- obj->Stopped = 1;
- obj->InMidAir = 0;
- // End the turn if there are still moving missiles after 600 ticks
- if(obj->ClType == OC_Missile)
- {
- if(TurnEnded)
- {
- if(GS->Tick - TurnEndTime > 300)
- {
- local missile = CMissile(obj);
- missile->ExplodeAt(missile->PosX, missile->PosY);
- }
- }
- }
- }
- void CMagnet::DoMagneticField(bool applyForce, bool forceWake)
- {
- float force = 0.0;
- if(applyForce) force = 1.0;
- for(int i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj->ClType == OC_Mine) ApplyForce(obj, force, forceWake);
- if(obj->ClType == OC_Missile) ApplyForce(obj, force, forceWake);
- // Support for bowling balls
- if(#WEAPON_BOWLINGBALL)
- {
- if(obj is CBowlingBall) ApplyForce(obj, force * 0.25, forceWake);
- }
- }
- }
- // Draws the magnetic ring effect
- void CMagnet::DrawMagnetRings()
- {
- if(NumRings>0)
- {
- CQuad q;
- q.blend = 1;
- for(local i = 0; i < NumRings; i+=1)
- {
- local size = GetRing(i) / 10;
- local alpha = ((RingMaxSize - GetRing(i)) * 255) / RingMaxSize;
- q.v[0].x = MagnetPosX - size; q.v[0].y = MagnetPosY - size;
- q.v[0].color = ARGB(alpha,255,255,255);
- q.v[1].x = MagnetPosX + size; q.v[1].y = MagnetPosY - size;
- q.v[1].color = ARGB(alpha,255,255,255);
- q.v[2].x = MagnetPosX + size; q.v[2].y = MagnetPosY + size;
- q.v[2].color = ARGB(alpha,255,255,255);
- q.v[3].x = MagnetPosX - size; q.v[3].y = MagnetPosY + size;
- q.v[3].color = ARGB(alpha,255,255,255);
- if(Polarity>0)
- {
- AddSpriteQ(ZPlane+1, &q, magnetRingSprite2->Index, 0, 64);
- }
- else
- {
- AddSpriteQ(ZPlane+1, &q, magnetRingSprite->Index, 0, 64);
- }
- }
- }
- }
- // Takes care of the animations
- void CMagnet::DoAnimation()
- {
- // Rings
- if(NumRings>0)
- {
- for(local i = 0; i < NumRings; i+=1)
- {
- SetRing(i, GetRing(i) + RingSpeed * Polarity);
- }
- if(Polarity>0)
- {
- if(GetRing(0)>RingMaxSize) PopRing();
- }
- else
- {
- if(GetRing(0)<RingMinSize) PopRing();
- }
- }
- if(TurnsRemaining>0 && Removed == false)
- {
- if(NextRing <= 0)
- {
- PushRing();
- NextRing = RingPeriod;
- }
- else
- {
- NextRing = NextRing - 1;
- }
- }
- // Sparks animation
- if(TurnsRemaining>0)
- {
- SparkCycle = SparkCycle + SparkAnimSpeed;
- if(SparkCycle > SparkCycleDuration) SparkCycle = SparkCycle - SparkCycleDuration;
- }
- }
- // Draws the magnet's sprite
- void CMagnet::DrawMagnet()
- {
- int sprite = Sprite1;
- if(Polarity<0)
- {
- if(Health<=LowHealth) sprite = Sprite1Damaged;
- else sprite = Sprite1;
- }
- else
- {
- if(Health<=LowHealth) sprite = Sprite2Damaged;
- else sprite = Sprite2;
- }
- if(Mirrored) sprite += 262144;
- AddSpriteEx(ZPlane, PosX, PosY, sprite, 0, Rotation + 3.14159, 1);
- }
- // Draws additional effects such as electrical sparks
- void CMagnet::DrawMagnetEffects()
- {
- if(TurnsRemaining>0)
- {
- if(SparkCycle <= 1.0)
- AddSpriteEx(ZPlane-1, PosX, PosY, magnetSparks->Index, SparkCycle, Rotation, 1);
- }
- }
- // Called when a new turn begins (this is used to discharge the magnet after a given number of turn cycles)
- void CMagnet::OnTurnBegin(int Team)
- {
- TurnEnded = false;
- TurnEndTime = 0;
- if(TurnsRemaining>0)
- {
- if(Team == OwnerTeam) TurnsRemaining = TurnsRemaining - 1;
- if(TurnsRemaining <= 0)
- {
- // Wake all nearby objects without applying force to them
- DoMagneticField(false, true);
- }
- }
- }
- void CMagnet::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- InitializeParameters();
- }
- if(Type == M_TURNEND)
- {
- TurnEnded = true;
- TurnEndTime = GS->Tick;
- }
- // Drawing operations are done here
- if(Type == M_DRAWQUEUE)
- {
- if(Initialized == false) return;
- UpdateMagnetPosition();
- DrawMagnetRings();
- if(Removed==false)
- {
- if(Mirrored) SetColorMod(RGB(0, 255, 0), 6);
- if(Sinking) SetColorMod(RGB(90, 90, 240), 6);
- DrawMagnet();
- if(Sinking) ClearColorMod();
- if(Mirrored) ClearColorMod();
- DrawMagnetEffects();
- // Recalculate Z plane periodically to make sure magnets are drawn properly when overlapping each other
- if(NextRecalcZPlane <= 0)
- {
- local matches = 0;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj == this) continue;
- if(obj->ClType == EObjectClass(70))
- {
- local mag = CMagnet(obj);
- float dX = mag->PosX - PosX;
- float dY = mag->PosY - PosY;
- float r2 = dX*dX + dY*dY;
- if(r2 < 900.0)
- {
- if(mag->ZPlane == ZPlane)
- {
- mag->ZPlane = mag->ZPlane + 2;
- }
- matches = matches + 1;
- }
- }
- }
- if(matches == 0) ZPlane = 10;
- NextRecalcZPlane = 200;
- }
- else
- {
- NextRecalcZPlane = NextRecalcZPlane - 1;
- }
- }
- return;
- }
- // Damage handling
- if(Removed==false)
- {
- if(Type == M_EXPLOSION)
- {
- if(IgnoreDamage) return;
- TakeExplosionDamage(MData->fparams[1], MData->fparams[2], MData->params[4]);
- }
- if(Type == M_GUNEXP)
- {
- if(IgnoreDamage) return;
- TakeDamage(MData->params[0], MData->params[5]);
- }
- }
- super;
- // This is done every frame (derp)
- if(Type == M_FRAME)
- {
- UpdateMagnetPosition();
- DoAnimation();
- if(Removed)
- {
- if(NumRings == 0) Free(true);
- return;
- }
- else
- {
- if(Sinking)
- {
- TurnsRemaining = 0;
- DoMagneticField(false, true);
- }
- else
- {
- UpdateRotation();
- }
- if(TurnsRemaining>0)
- {
- // Apply magnetic force to nearby objects but don't wake them if the magnet is standing still
- DoMagneticField(true, false);
- }
- // No more health -> KA-BEWM!
- if(Health <= 0)
- {
- // Wake all nearby objects without applying force to them
- DoMagneticField(false, true);
- DoExplosion(PosX,PosY-20, ExplosionBlast, ExplosionDamage, 0, 0);
- Removed = true;
- SpeedDivider = 1000;
- SpX = 0.0;
- SpY = 0.0;
- GravityFactor = 0.0;
- IsMaterial = false;
- Stopped = 1;
- }
- }
- }
- }
- ///////////////////////////////////////////////////
- // CMagnetMissile class
- CMagnetMissile : CMagnet;
- CMagnetMissile::CMagnetMissile(CObject* Parent, CShootDesc* Desc, int WormDir, int Pol)
- {
- super;
- // Maximum distance in which objects can be affected by the magnet
- MaxRange = 120.0;
- // Maximum acceleration the magnet can apply
- MaxForce = 12.0;
- // How much the force applied by the magnet is multiplied
- ForceCoefficient = 12000.0;
- // This value is added to the squared distance to avoid divisions by zero, it also gives the magnet a less violent behaviour
- // on objects which are near the center
- AttractOffset = 20.0;
- RepelOffset = 10.0;
- // If set to true, magnets in attract mode will attempt to synchronize caught random mines
- // so they explode at the same time, causing maximum damage
- MineTriggerSync = true;
- // How many cycles of turns before the magnet stops working
- TurnsRemaining = 2;
- // How much damage the magnet can take before breaking
- Health = 20;
- ExplosionDamage = 40;
- ExplosionBlast = 100;
- // Ignore any damage taken
- IgnoreDamage = true;
- // Offset between the projectile and the actual magnetic field
- MagnetOffsetX = -14.0;
- MagnetOffsetY = 0.0;
- MagnetOffsetRelative = true;
- // END OF MAGNET PARAMETERS
- // Sprite parameters
- Sprite1 = magmissileSprite->Index;
- Sprite2 = magmissileSprite2->Index;
- Sprite1Damaged = magmissileSprite->Index;
- Sprite2Damaged = magmissileSprite2->Index;
- // Animation parameters
- SpinMultiplier = 0.04;
- MaxSpinSpeed = 0.5;
- RingSpeed = 12;
- RingPeriod = 30;
- RingMinSize = 5;
- RingMaxSize = 60;
- OrientationOption = 1;
- // Private
- Phase = 0;
- AttachX = 0.0;
- AttachY = 0.0;
- LastSpX = SpX;
- LastSpY = SpY;
- }
- // Collisions derp
- void CMagnetMissile::Collide(CGObject* Obj, int type)
- {
- if(Phase == 0)
- {
- float speed = sqrt(LastSpX * LastSpX + LastSpY * LastSpY);
- // Collided with the world
- if(Obj->ClType == OC_Landscape)
- {
- int hitx;
- int hity;
- float s = sin(Rotation);
- float c = cos(Rotation);
- float dx = 0 - (s * 8.0);
- float dy = c * 8.0;
- // Perform a trace 8 units forwards
- CGObject *hit = TraceLine(this, PosX, PosY, PosX + dx, PosY + dy, 2, &hitx, &hity);
- if(hit != NullObj)
- {
- // The trace hit the world, make the missile stick
- if(hit->ClType == OC_Landscape)
- {
- AttachX = PosX;
- AttachY = PosY;
- SpeedDivider = 1000;
- SpeedDividerB = 1000;
- SpX = 0.0;
- SpY = 0.0;
- GravityFactor = 0.0;
- Stopped = 1;
- InMidAir = 0;
- Phase = 1;
- // Arrow impact sound
- PlayLocalSound(28, 5, 1.0, 1.0);
- IgnoreDamage = false;
- OrientationOption = 0;
- return;
- }
- }
- else if(speed>5.0)
- {
- // Didn't hit the world at a suitable angle, reflect it if it has enough speed
- super;
- return;
- }
- // Not enough speed, make it roll away
- IgnoreDamage = false;
- OrientationOption = 0;
- Phase = 2;
- }
- else // Collided with something else
- {
- bool nodamage = false;
- // Bounce off oil drums and crates without dealing any damage
- if(Obj->ClType == OC_OilDrum) nodamage = true;
- if(Obj->ClType == OC_Crate) nodamage = true;
- if(nodamage)
- {
- IgnoreDamage = false;
- OrientationOption = 0;
- Phase = 2;
- super;
- return;
- }
- // Knock colliding objects away
- fixed forceX;
- fixed forceY;
- if(speed>0.5)
- {
- forceX = LastSpX * 0.3;
- forceY = (LastSpY - speed) * 0.3;
- // This will ensure the missile keeps going right through whatever it collided with
- // (see CMagnetMissile::Message)
- PostCollide = true;
- CMessageData msg;
- msg.params[0] = 0;
- msg.fparams[1] = PosX;
- msg.fparams[2] = PosY;
- msg.fparams[3] = forceX;
- msg.fparams[4] = forceY;
- msg.params[5] = 5;
- msg.params[6] = 0;
- Obj->Message(this, M_GUNEXP, 1032, &msg);
- // PUNCH!
- PlayLocalSound(101, 5, 1.0, 1.0);
- return;
- }
- else
- {
- IgnoreDamage = false;
- OrientationOption = 0;
- Phase = 2;
- super;
- return;
- }
- }
- }
- super;
- }
- void CMagnetMissile::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Phase == 1)
- {
- bool checkdetach = false;
- bool detach = true;
- // Took damage, see if it should detach or not
- if(Type == M_EXPLOSION) { checkdetach = true; detach = false; }
- else if(Type == M_GUNEXP)
- {
- // Detach it no matter what if melee damage has been received (aka type != 1 and 3)
- checkdetach = true;
- if(MData->params[0] == 1) detach = false;
- if(MData->params[0] == 3) detach = false;
- }
- if(checkdetach)
- {
- if(detach == false)
- {
- // Damage has been dealt by fire, bullets or explosions, check if the missile still has an attachment point
- int hitx;
- int hity;
- float s = sin(Rotation);
- float c = cos(Rotation);
- float dx = 0 - (s * 8.0);
- float dy = c * 8.0;
- // Perform a trace 8 units forwards
- CGObject *hit = TraceLine(this, PosX, PosY, PosX + dx, PosY + dy, CMASK_TERRAIN, &hitx, &hity);
- // Not attached to world anymore, detach it
- if(hit == NullObj) detach = true;
- else if(hit->ClType != OC_Landscape) detach = true;
- }
- // Detaching :(
- if(detach)
- {
- AttachX = 0.0;
- AttachY = 0.0;
- SpeedDivider = 1;
- SpeedDividerB = 1;
- GravityFactor = 1.0;
- Stopped = 0;
- InMidAir = 1;
- Phase = 2;
- }
- }
- }
- super;
- if(Type == M_FRAME)
- {
- if(Phase == 0)
- {
- if(Sinking == false)
- {
- local p = new PxParticle(131, MagnetPosX, MagnetPosY);
- p->SetLifeTime(30);
- p->SetRandomVelocity(0.2, 0.6);
- p->SetAirResistance(0.5);
- p->SetAlpha(255);
- if(Polarity==1)
- {
- p->SetColor(60,80,190);
- }
- else
- {
- p->SetColor(200,60,60);
- }
- }
- }
- if(Phase == 1)
- {
- PosX = AttachX;
- PosY = AttachY;
- SpX = 0.0;
- SpY = 0.0;
- Stopped = 1;
- InMidAir = 0;
- }
- if(PostCollide)
- {
- // Collided with something it should go right through
- // Set its velocity back to what it was before the collision
- SpX = LastSpX;
- SpY = LastSpY;
- PostCollide = false;
- }
- LastSpX = SpX;
- LastSpY = SpY;
- }
- }
- ///////////////////////////////////////////////////
- // CTurnGame overrides
- override void CTurnGame::SetCurrentTeam(int Team)
- {
- super;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj is CMagnet)
- {
- CMagnet *mag = CMagnet(obj);
- mag->OnTurnBegin(Team);
- }
- }
- }
- ///////////////////////////////////////////////////
- // CWorm overrides
- override CWorm::CWorm(CObject* Parent, int aTeam, int aIndex, CWormParams* params)
- {
- super;
- MagnetPolarity = 0;
- AnimCanChangeMagnetType = false;
- }
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Electromagnet"))
- {
- local ang = (1 - FireAngle) * 3.14159;
- if (TurnSide < 0)
- {
- ang = 6.28318 - ang;
- }
- CShootDesc SDesc;
- zero(&SDesc);
- local BaseForce = 0.3;
- SDesc.Team = WormTeam;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = SpX + TurnSide * BaseForce;
- SDesc.SpY = SpY - 0.15;
- int polarity = 1;
- if(MagnetPolarity==1) polarity = -1;
- new CMagnet(GetObject(25, 0), &SDesc, TurnSide, polarity);
- }
- else if(Weap->CheckName("Magnetic Missile"))
- {
- local ang = (1 - FireAngle) * 3.14159;
- if (TurnSide < 0)
- {
- ang = 6.28318 - ang;
- };
- CShootDesc SDesc;
- zero(&SDesc);
- float BaseForce = FirePower * 20.0;
- SDesc.Team = WormTeam;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = SpX + sin(ang) * BaseForce;
- SDesc.SpY = SpY - cos(ang) * BaseForce;
- int polarity = 1;
- if(MagnetPolarity==1) polarity = -1;
- new CMagnetMissile(GetObject(25, 0), &SDesc, TurnSide, polarity);
- }
- else
- {
- super;
- }
- }
- override void CWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if (CurWeapon->CheckName("Electromagnet"))
- {
- local Team = CTeam(GetObject(21, WormTeam));
- Team->AllowSelectBounce = true;
- //if(MagnetPolarity==1) CurWeapon->NameB = "Electromagnet, ATTRACT Mode";
- //else CurWeapon->NameB = "Electromagnet, REPEL Mode";
- }
- else if (CurWeapon->CheckName("Magnetic Missile"))
- {
- local Team = CTeam(GetObject(21, WormTeam));
- Team->AllowSelectBounce = true;
- }
- }
- if (Type == M_SETBOUNCE)
- {
- if (CurWeapon->CheckName("Electromagnet"))
- {
- if (MData->GetParameter(1) != WormNumber) return;
- local Dir = MData->GetParameter(2);
- if(MagnetPolarity != Dir)
- {
- MagnetPolarity = Dir;
- if(AnimCanChangeMagnetType) // Don't replay the deploy animation if we're not standing still
- {
- Anim->SetAnim(334); // Dynamite deploy animation
- }
- }
- if(Dir==1) ShowMessage("Electromagnet, ATTRACT Mode");
- else ShowMessage("Electromagnet, REPEL Mode");
- return;
- }
- else if (CurWeapon->CheckName("Magnetic Missile"))
- {
- if (MData->GetParameter(1) != WormNumber) return;
- local Dir = MData->GetParameter(2);
- MagnetPolarity = Dir;
- if(Dir==1) ShowMessage("Magnetic Missile, ATTRACT Mode");
- else ShowMessage("Magnetic Missile, REPEL Mode");
- return;
- }
- }
- //if(Type == M_DRAWQUEUE)
- //{
- // int sx;
- // int sy;
- //
- // AnimDebugBitmap->Rect(0,0,299,35,ARGB(255,0,0,0));
- // GS->Disp->DrawText(1, AnimDebugBitmap, 5, 3, AnimDebugText, &sx, &sy);
- //
- // int RenderX = -GS->ResX / 2 + 165;
- // int RenderY = -GS->ResY / 2 + 55;
- // AddInterfaceBitmap(1, RenderX, RenderY, AnimDebugBitmap, 0, 0, 300, 100,0);
- //}
- super;
- }
- ///////////////////////////////////////////////////
- // CSpriteAnim overrides
- override void CSpriteAnim::SetAnimEx(int sindex, fixed frame)
- {
- // Make sure the game has actually started (otherwise GetCurrentWorm would crash the game due to Root not existing)
- if(GS->Tick >= 1)
- {
- // If we belong to the current worm
- CWorm *w = GetCurrentWorm();
- if(w != NullObj && w->Anim == this)
- {
- //int f = int(frame * 1000.0);
- //string temp = MakeNumberString(" Frame: ", f, "");
- //AnimDebugText = MakeNumberString("Anim: ", sindex, temp);
- if(sindex == 334 && w->CurWeapon->CheckName("Electromagnet")) // Dynamite deploy animation
- {
- if(w->MagnetPolarity == 1)
- {
- // Red magnet deploy animation
- super(wmaglnk->Index, frame);
- }
- else
- {
- // Blue magnet deploy animation
- super(wmag2lnk->Index, frame);
- }
- w->AnimCanChangeMagnetType = true;
- return;
- }
- else
- {
- w->AnimCanChangeMagnetType = false;
- }
- }
- }
- super;
- }
- PXS : Library Code :
- require pxairstrike, pxparticles, utils, wp_magnets, wpsounds;
- PxAirstrikeParams *BunkerBusterParams;
- CFireDesc *BunkerBusterFireDesc;
- //CSprite* bunkerbusterSprite;
- //CSprite* superbunkerbusterSprite;
- CSprite *bbIdleSprite;
- CSprite *bbDiggingSprite;
- CSprite *sbbIdleSprite;
- CSprite *sbbDiggingSprite;
- CSprite *sbbGlowSprite;
- CSoundFile* bunkerbusterDrillSound;
- CSoundFile* bunkerbusterFallSound;
- CColMask* MASK_BUNKERBUSTER;
- CMagnetResult *BunkerBusterMagnetResult;
- void bunkerbuster::FirstFrame()
- {
- BunkerBusterParams = new PxAirstrikeParams;
- BunkerBusterFireDesc = new CFireDesc;
- BunkerBusterFireDesc->Count = 10;
- BunkerBusterFireDesc->UnkB = 1;
- BunkerBusterFireDesc->Duration = 1000;
- BunkerBusterFireDesc->UpPower = 15;
- BunkerBusterFireDesc->Damage = 1;
- BunkerBusterFireDesc->OwnerTeam = 0;
- MASK_BUNKERBUSTER = new CColMask(8, 8, MakeCircleMask(8));
- CFile *f;
- f = GetAttachment("bunkbustdrill.wav");
- bunkerbusterDrillSound = new CSoundFile(f);
- f = GetAttachment("bunkbustfall.wav");
- bunkerbusterFallSound = new CSoundFile(f);
- BunkerBusterMagnetResult = new CMagnetResult();
- }
- // Loading resources
- void bunkerbuster::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("bbuster_idle.png");
- bbIdleSprite = LoadSprite(f, 3, 0);
- f = GetAttachment("bbuster_digging.png");
- bbDiggingSprite = LoadSprite(f, 3, 0);
- f = GetAttachment("sbbuster_idle.png");
- sbbIdleSprite = LoadSprite(f, 3, 0);
- f = GetAttachment("sbbuster_digging.png");
- sbbDiggingSprite = LoadSprite(f, 3, 0);
- f = GetAttachment("sbbuster_glow.png");
- sbbGlowSprite = LoadSprite(f, 1, 0);
- //f = GetAttachment("bunkerbuster.png");
- //bunkerbusterSprite = LoadSprite(f, 3, 0);
- //f = GetAttachment("superbunkerbuster.png");
- //superbunkerbusterSprite = LoadSprite(f, 3, 0);
- }
- ///////////////////////////////////////////////////
- // PxBunkerBusterStrike
- PxBunkerBusterStrike : PxAirstrike
- PxBunkerBusterStrike::PxBunkerBusterStrike(CObject* Parent, CShootDesc* Desc, PxAirstrikeParams* Params, int type)
- {
- super(Parent, Desc, Params);
- BusterType = type;
- }
- void PxBunkerBusterStrike::DropBomb()
- {
- CShootDesc SDesc;
- zero(&SDesc);
- SDesc.Team = Team;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = 0;
- SDesc.SpY = 0;
- new PxBunkerBuster(Root->GetObject(25, 0), &SDesc, BusterType);
- }
- void PxBunkerBusterStrike::RenderPlane()
- {
- SetColorMod(RGB(255, 140, 0), 6); // orange plane!
- super;
- ClearColorMod();
- }
- ///////////////////////////////////////////////////
- // PxBunkerBuster
- PxBunkerBuster : CMine
- PxBunkerBuster::PxBunkerBuster(CObject* Parent, CShootDesc* Desc, int type)
- {
- CMineParams MParams;
- zero(&MParams);
- MParams.Prefuse = 0;
- MParams.Radius = 0;
- MParams.Fuse = 1;
- MParams.Flags = 0;
- MParams.Bias = 0;
- MParams.Damage = 0;
- MParams.BlastPower = 0;
- super(Parent, &MParams, Desc, false, 0);
- // parameters
- DrillFuelAmount = float(220.0);
- DrillMinSpeed = float(1.0);
- DrillMaxSpeed = float(4.0);
- DiggingMagnetFactor = float(3.0);
- DirX = float(0.0);
- DirY = float(1.0);
- AnimSpeed = 0.08;
- ExplosionDeltaTime = 8;
- ExplosionDistance = 40;
- if(type == 0)
- {
- //Sprite = bunkerbusterSprite->Index;
- SpriteIdle = bbIdleSprite->Index;
- SpriteDigging = bbDiggingSprite->Index;
- SpriteGlow = 0;
- NumExplosions = 1;
- ExplosionBlast = 100;
- ExplosionDamage = 38;
- }
- else
- {
- //Sprite = superbunkerbusterSprite->Index;
- SpriteIdle = sbbIdleSprite->Index;
- SpriteDigging = sbbDiggingSprite->Index;
- SpriteGlow = sbbGlowSprite->Index;
- NumExplosions = 5;
- ExplosionBlast = 80;
- ExplosionDamage = 26;
- }
- DrillFireMinDelta = 15;
- DrillFireMaxDelta = 60;
- // internal - do not change
- ClType = EObjectClass(72);
- Dead = false;
- Drilling = false;
- DrillSpeed = DrillMinSpeed;
- AnimCycle = 0.0;
- AnimCycleDuration = 1.0;
- ExhaustType = 0;
- ColMask = MASK_BUNKERBUSTER;
- Team = Desc->Team;
- ChangeDrillSpeedTimer = 0;
- DrillSoundTimer = 0;
- BusterType = type;
- ExplosionNum = 0;
- ExplosionTimer = 0;
- DrillFireTimer = 0;
- Rotation = 0.0;
- ColGroupDigging = CMASK_TERRAIN
- | CMASK_WORM_ON_TERRAIN
- | CMASK_WORM_USING_WEAPON
- | CMASK_WORM_IN_MIDAIR
- | CMASK_WORM_ON_ROPE
- | CMASK_WORM_FROZEN
- | CMASK_GASCANISTER
- | CMASK_MINE
- | CMASK_CRATE
- | CMASK_DONORCARD
- | CMASK_OILDRUM
- | CMASK_SKIMMING;
- ColGroupDefault = ColGroupDigging | CMASK_TERRAIN;
- ColGroup = ColGroupDefault;
- SoundObj = CSound(NullObj);
- bunkerbusterFallSound->Play(1.0, 0.0, false);
- MaxMagnetForce = 0.1;
- LastPosX = PosX;
- LastPosY = PosY;
- }
- void PxBunkerBuster::UpdateRotation()
- {
- if(SpX==0.0)
- {
- if(SpY>0.0)
- {
- Rotation = 0.0;
- }
- else if(SpY<0.0)
- {
- Rotation = 3.141593;
- }
- }
- else
- {
- Rotation = -atan2(SpX, SpY);
- }
- }
- void PxBunkerBuster::StartDigging()
- {
- Drilling = true;
- ExhaustType = 1;
- GravityFactor = 0.0;
- SoundObj = bunkerbusterDrillSound->Play(1.0, 0.0, false);
- LastPosX = PosX;
- LastPosY = PosY;
- } //seems like colgroup changing in Collide hook causes game freezing
- void PxBunkerBuster::StopDigging()
- {
- Drilling = false;
- GravityFactor = 1.0;
- // ColGroup = ColGroupDefault;
- if(SoundObj != CSound(NullObj))
- {
- // Mute the sound
- SoundObj->Update(0.0, 0.0);
- }
- }
- void PxBunkerBuster::Explode()
- {
- if(Dead) return;
- SetDirection(SpX, SpY);
- StopDigging();
- //DoExplosion(1, PosX, PosY, ExplosionBlast, ExplosionDamage, 0, 0);
- SpX = 0.0;
- SpY = 0.0;
- GravityFactor = 0.0;
- IsMaterial = false;
- Stopped = 1;
- Dead = true;
- }
- void PxBunkerBuster::SetDirection(float dx, float dy)
- {
- if(Dead) return;
- float d = sqrt(dx*dx+dy*dy);
- if(d < 0.0001 && d > -0.0001)
- {
- DirX = 0;
- DirY = 1;
- }
- else
- {
- DirX = dx / d;
- DirY = dy / d;
- }
- }
- void PxBunkerBuster::Collide(CGObject* Obj, int type)
- {
- if(Obj->ClType == OC_Landscape)
- {
- if(Drilling == false)
- {
- if(DrillFuelAmount <= 0)
- {
- Explode();
- return;
- }
- StartDigging();
- }
- }
- else
- {
- Explode();
- }
- }
- void PxBunkerBuster::DoExplosion(fixed x, fixed y, int PushPower, int Damage, int unkB, int team)
- {
- super;
- if(BusterType > 0)
- {
- BunkerBusterFireDesc->Count = 6;
- BunkerBusterFireDesc->X = x;
- BunkerBusterFireDesc->Y = y;
- BunkerBusterFireDesc->SpX = 0;
- BunkerBusterFireDesc->SpY = 0;
- new CFire(GetObject(TI_FireStore, 0), BunkerBusterFireDesc, 0);
- }
- }
- void PxBunkerBuster::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- // Drawing operations are done here
- if(Type == M_DRAWQUEUE)
- {
- if(Dead) return;
- if(Sinking)
- {
- SetColorMod(RGB(90, 90, 240), 6);
- }
- CQuad q;
- q.blend = 0;
- for(int k=0 ; k<4 ; k+=1) q.v[k].color = RGB(255,255,255);
- //AddSprite(10, PosX, PosY, 0, Sprite, AnimCycle);
- if(Drilling)
- {
- //AddSpriteEx(10.01, PosX, PosY, SpriteDigging, AnimCycle, Rotation, 1.0);
- FillSpriteQuad(&q, SpriteDigging, 0, 0);
- TransformQuad(&q, Rotation, 1.0, 1.0, PosX, PosY);
- AddSpriteQ(10.01, &q, SpriteDigging, AnimCycle, 0);
- }
- else
- {
- //AddSpriteEx(10.01, PosX, PosY, SpriteIdle, AnimCycle, Rotation, 1.0);
- FillSpriteQuad(&q, SpriteIdle, 0, 0);
- TransformQuad(&q, Rotation, 1.0, 1.0, PosX, PosY);
- AddSpriteQ(10.01, &q, SpriteIdle, AnimCycle, 0);
- }
- if(Sinking)
- {
- ClearColorMod();
- }
- else if(SpriteGlow > 0)
- {
- FillSpriteQuad(&q, SpriteGlow, 0, 0);
- TransformQuad(&q, Rotation, 1.0, 1.0, PosX, PosY);
- q.blend = 1;
- for(int i=0 ; i<4 ; i+=1) q.v[i].color = RGB(255,70,0);
- AddSpriteQ(10, &q, SpriteGlow, 0, 64);
- }
- return;
- }
- super;
- // This is done every frame
- if(Type == M_FRAME)
- {
- if(Dead)
- {
- if(ExplosionNum >= NumExplosions)
- {
- Free(true);
- return;
- }
- if(ExplosionTimer <= 0)
- {
- float dist = ExplosionDistance * ExplosionNum;
- DoExplosion(PosX + DirY * dist, PosY - DirX * dist, ExplosionBlast, ExplosionDamage, 0, 0);
- if(ExplosionNum > 0)
- {
- DoExplosion(PosX - DirY * dist, PosY + DirX * dist, ExplosionBlast, ExplosionDamage, 0, 0);
- }
- ExplosionTimer = ExplosionDeltaTime;
- ExplosionNum = ExplosionNum + 1;
- }
- ExplosionTimer = ExplosionTimer - 1;
- }
- if(Sinking == false)
- {
- UpdateRotation();
- // Animation
- AnimCycle = AnimCycle + AnimSpeed;
- if(AnimCycle > AnimCycleDuration) AnimCycle = AnimCycle - AnimCycleDuration;
- BunkerBusterMagnetResult->Reset();
- BunkerBusterMagnetResult->CalculateGlobalMagneticForce(PosX, PosY, 0.4);
- if(BunkerBusterMagnetResult->IsNull == false && BunkerBusterMagnetResult->ForceX == 0.0)
- {
- BunkerBusterMagnetResult->ForceX = 0.01;
- }
- if(Drilling)
- {
- ColGroup = ColGroupDigging;
- float force = sqrt(
- BunkerBusterMagnetResult->ForceX * BunkerBusterMagnetResult->ForceX +
- BunkerBusterMagnetResult->ForceY * BunkerBusterMagnetResult->ForceY
- );
- if(force > MaxMagnetForce)
- {
- force = MaxMagnetForce / force;
- BunkerBusterMagnetResult->ForceX = BunkerBusterMagnetResult->ForceX * force;
- BunkerBusterMagnetResult->ForceY = BunkerBusterMagnetResult->ForceY * force;
- }
- SetDirection(
- 10 * DirX + DiggingMagnetFactor * BunkerBusterMagnetResult->ForceX,
- 10 * DirY + DiggingMagnetFactor * BunkerBusterMagnetResult->ForceY
- );
- //if(DrillSoundTimer <= 0)
- //{
- // PlayLocalSound(84, 0, 1.0, 1.0, &Snd);
- // DrillSoundTimer = 40;
- //}
- //
- //DrillSoundTimer = DrillSoundTimer - 1;
- // Change the speed of the buster every random interval
- if(ChangeDrillSpeedTimer <= 0)
- {
- DrillSpeed = RandomFloat(DrillMinSpeed, DrillMaxSpeed);
- ChangeDrillSpeedTimer = RandomInt(5, 15);
- }
- ChangeDrillSpeedTimer = ChangeDrillSpeedTimer - 1;
- // If we're a super bunker buster, spread fire around
- if(BusterType > 0)
- {
- if(DrillFireTimer <= 0)
- {
- BunkerBusterFireDesc->Count = 1;
- BunkerBusterFireDesc->X = PosX;
- BunkerBusterFireDesc->Y = PosY;
- BunkerBusterFireDesc->SpX = RandomFloat(-2.0, 2.0);
- BunkerBusterFireDesc->SpY = -4;
- new CFire(GetObject(TI_FireStore, 0), BunkerBusterFireDesc, 0);
- DrillFireTimer = RandomInt(DrillFireMinDelta, DrillFireMinDelta);
- }
- DrillFireTimer = DrillFireTimer - 1;
- }
- // Using the same mask as the Pneumatic Drill (mask 2)
- SpX = DirX * DrillSpeed;
- SpY = DirY * DrillSpeed;
- int h_offset1 = RandomInt(6, 11);
- int h_offset2 = RandomInt(5, 10);
- //GG->land->ApplyMask(2, PosX + OffsetX, PosY);
- GG->land->ApplyMask(1, PosX, PosY);
- GG->land->ApplyMask(13, PosX + DirY * h_offset1, PosY - DirX * h_offset1);
- GG->land->ApplyMask(13, PosX - DirY * h_offset2, PosY + DirX * h_offset2);
- float dx = PosX - LastPosX;
- float dy = PosY - LastPosY;
- float distance = sqrt(dx*dx + dy*dy);
- DrillFuelAmount -= distance;
- //DrillFuelAmount -= DrillSpeed;
- LastPosX = PosX;
- LastPosY = PosY;
- // Enough drilling, blow up now!
- if(DrillFuelAmount <= 0.0)
- {
- Explode();
- return;
- }
- // If there is no more land to drill, go back to falling mode
- if(FindInMask(this, ColMask, PosX + 10.0*DirX, PosY + 10.0*DirY, 2) == NullObj)
- {
- // Give it a little push if it's not drilling directly downwards
- SpX += 2 * (1.0 - DirY) * DirX * DrillSpeed;
- SpY += 2 * (1.0 - DirY) * DirY * DrillSpeed;
- StopDigging();
- }
- }
- else
- {
- ColGroup = ColGroupDefault;
- if(BunkerBusterMagnetResult->IsNull == false)
- {
- SpX += BunkerBusterMagnetResult->ForceX;
- SpY += BunkerBusterMagnetResult->ForceY;
- }
- SetDirection(SpX, SpY);
- }
- // Smoke particles
- if(ExhaustType == 0)
- {
- local p = new PxParticle(131, PosX - 14 * DirX, PosY - 14 * DirY);
- p->SetLifeTime(30);
- p->SetRandomVelocity(0.2, 0.5);
- p->SetAirResistance(0.5);
- p->SetStartAlpha(255);
- p->SetEndAlpha(255);
- p->SetStartColor(255,255,255);
- p->SetEndColor(255,255,255);
- }
- else
- {
- if(BusterType == 0)
- {
- local p = new PxParticle(131, PosX + 14 * DirY - 12 * DirX, PosY - 14 * DirX - 12 * DirY);
- p->SetLifeTime(30);
- p->SetRandomVelocity(0.5, 0.8);
- p->SetAirResistance(0.5);
- p->SetStartAlpha(140);
- p->SetEndAlpha(140);
- p->SetStartSize(0.5, 0.5);
- p->SetEndSize(0.5, 0.5);
- p->SetStartColor(200,200,200);
- p->SetEndColor(50,50,50);
- }
- else
- {
- local p = new PxParticle(130, PosX + 14 * DirY - 10 * DirX, PosY - 12 * DirX - 10 * DirY);
- p->SetLifeTime(30);
- p->SetBlendMode(1);
- p->SetRandomVelocity(0.5, 0.8);
- p->SetAirResistance(0.5);
- p->SetStartAlpha(255);
- p->SetEndAlpha(255);
- p->SetStartSize(0.5, 0.5);
- p->SetEndSize(0.5, 0.5);
- p->SetColor(150,150,150);
- p = new PxParticle(130, PosX - 14 * DirY - 10 * DirX, PosY + 12 * DirX - 10 * DirY);
- p->SetLifeTime(30);
- p->SetBlendMode(1);
- p->SetRandomVelocity(0.5, 0.8);
- p->SetAirResistance(0.5);
- p->SetStartAlpha(255);
- p->SetEndAlpha(255);
- p->SetStartSize(0.5, 0.5);
- p->SetEndSize(0.5, 0.5);
- p->SetColor(150,150,150);
- }
- }
- }
- }
- }
- ///////////////////////////////////////////////////
- // CWorm overrides
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Bunker Buster"))
- {
- BunkerBusterParams->NumBombs = 1;
- BunkerBusterParams->BombDistance = 64;
- BunkerBusterParams->BombSpX = 0;
- BunkerBusterParams->BombSpY = 0;
- new PxBunkerBusterStrike(GetObject(25, 0), Desc, BunkerBusterParams, 0);
- }
- else if(Weap->CheckName("Super Bunker Buster"))
- {
- BunkerBusterParams->NumBombs = 1;
- BunkerBusterParams->BombDistance = 64;
- BunkerBusterParams->BombSpX = 0;
- BunkerBusterParams->BombSpY = 0;
- new PxBunkerBusterStrike(GetObject(25, 0), Desc, BunkerBusterParams, 1);
- }
- else
- {
- super;
- }
- }
- override void CWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_SPACE)
- {
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj is PxBunkerBuster)
- {
- local bb = PxBunkerBuster(obj);
- if(bb->Team == WormTeam)
- {
- bb->Explode();
- return;
- }
- }
- }
- }
- super;
- }
- PXS : Library Code :
- require utils, pxparticles, wpsounds;
- #WEAPON_FAN
- CSprite* fanBodySprite;
- CSprite* fanBladeSprite;
- CSprite* fanBladeIdleSprite;
- CSprite* fanGrateSprite;
- CSprite* fanArrowSprite;
- CColMask* MASK_FAN;
- CColMask* MASK_FANBLADE_DMG;
- int WEAPONINDEX_FAN;
- //CLogFile *fanLog;
- PxWindManager : CObject;
- PxFan : CMine;
- PxWindManager *WIND_M;
- void fan::FirstFrame()
- {
- MASK_FAN = new CColMask(6, 12, MakeRectMask(6, 12));
- MASK_FANBLADE_DMG = new CColMask(12, 28, MakeRectMask(12, 28));
- WIND_M = new PxWindManager();
- //fanLog = new CLogFile("fan_log.txt");
- WEAPONINDEX_FAN = -1;
- }
- // Loading resources
- void fan::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("fan_body.png"); fanBodySprite = LoadSprite(f, 1, 0);
- f = GetAttachment("fan_blade.png"); fanBladeSprite = LoadSprite(f, 4, 0);
- f = GetAttachment("fan_blade_idle.png"); fanBladeIdleSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("fan_grate.png"); fanGrateSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("fan_arrow.png"); fanArrowSprite = LoadSprite(f, 1, 0);
- }
- ///////////////////////////////////////////////////
- // PxWindManager class
- PxWindManager::PxWindManager()
- {
- super(Root, GS);
- InitialWind = 0.0; // The wind at the beginning of the turn
- ShouldRecalcWind = false; // Should we recalculate the total wind from every active fan?
- }
- void PxWindManager::InitWind()
- {
- InitialWind = GS->env->Wind;
- }
- void PxWindManager::RecalculateWind()
- {
- ShouldRecalcWind = false;
- float wind = InitialWind;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj is PxFan)
- {
- local obj_fan = PxFan(obj);
- wind += obj_fan->GetWindForce();
- }
- }
- if(wind > 0.34) wind = 0.34;
- if(wind < -0.34) wind = -0.34;
- GS->env->Wind = wind;
- CMessageData msg;
- msg.fparams[0] = wind;
- Root->Message(Root, M_UPDATEWIND, 1032, &msg);
- }
- void PxWindManager::UpdateWind()
- {
- ShouldRecalcWind = true;
- }
- void PxWindManager::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if(ShouldRecalcWind)
- {
- RecalculateWind();
- }
- }
- if(Type == M_DRAWQUEUE)
- {
- return;
- }
- super;
- }
- ///////////////////////////////////////////////////
- // PxFan class
- PxFan::PxFan(CObject* Parent, CShootDesc* Desc, int force, int mode, int side)
- {
- // Health parameters
- if(mode == 0)
- MaxHealth = 55;
- else
- MaxHealth = 40;
- Health = MaxHealth;
- ExplosionDamage = 25;
- ExplosionBlast = 50;
- DamagePerBladeHit = 14;
- DamageReductionPerHit = 4; // 14+10+6+2+1+1+1...
- DamageTakenPerBladeHit = 3;
- BladeHitForce = 5.0;
- BladeCooldown = 5;
- // Physics parameters
- BounceMultiplierX = 0.0;
- BounceMultiplierY = 1.0;
- // INTERNAL PARAMETERS
- FanMode = mode;
- FanForce = force;
- TurretScale = 0.6;
- // Sprites
- SpriteBody = fanBodySprite->Index;
- SpriteBlade = fanBladeSprite->Index;
- SpriteBladeIdle = fanBladeIdleSprite->Index;
- SpriteGrate = fanGrateSprite->Index;
- SpriteArrow = fanArrowSprite->Index;
- // Private
- AnimCycle = 0.0;
- // Arrow animation
- NumArrows = 0;
- Arrows = new int[6];
- for(local i=0 ; i<6 ; i+=1) Arrows[i] = 0;
- NextArrow = 0;
- ArrowSpeed = 2 + FanForce * 3;
- ArrowPeriod = 40 / FanForce;
- ArrowDistance = 6 + FanForce * 12;
- ArrowScale = 1.0 + FanForce * 0.1;
- AnimSpeed = 0.0;
- MaxAnimSpeed = 0.06 + FanForce * 0.025;
- TargetAnimSpeed = MaxAnimSpeed;
- AnimAccel = 0.006;
- NextBladeCooldown = 30;
- BaseOffsetX = 0;
- BaseOffsetY = -1;
- BladeOffsetX = 10;
- BladeOffsetY = -14;
- GrateOffsetX = 10;
- GrateOffsetY = -14;
- Planted = false;
- Removed = false;
- TurnsRemaining = 7 - FanForce;
- DestroyOnExpire = false;
- //if(Desc->SpX < 0)
- if(side < 0)
- {
- BaseSide = -1;
- }
- else
- {
- BaseSide = 1;
- }
- NextRecalcZPlane = 0;
- ZPlane = 10.0;
- OwnerTeam = Desc->Team;
- BladePosX = PosX;
- BladePosY = PosY;
- CMineParams MParams;
- zero(&MParams);
- MParams.Prefuse = 0;
- MParams.Flags = 0;
- MParams.Bias = 0;
- MParams.Radius = 0;
- MParams.Fuse = 71;
- MParams.Damage = 48;
- MParams.BlastPower = 100;
- SetLayerOverride(LAYER_OILDRUM);
- SetMaskIndexOverride(3);
- super(Parent, &MParams, Desc, false, 0);
- ClType = EObjectClass(74);
- //Layer = LAYER_OILDRUM;
- //ColGroup = CMASK_DEFAULT_COLLIDEABLE;
- ColMask = MASK_FAN;
- WIND_M->UpdateWind();
- }
- bool PxFan::IsActive()
- {
- return (Removed == false) && (TurnsRemaining > 0);
- }
- void PxFan::Recharge()
- {
- if(Removed) return;
- if(TurnsRemaining <= 0)
- {
- NextArrow = 0;
- }
- TurnsRemaining = 7 - FanForce;
- WIND_M->UpdateWind();
- }
- void PxFan::OnTurnBegin(int Team)
- {
- if(TurnsRemaining>0)
- {
- if(Team == OwnerTeam) TurnsRemaining = TurnsRemaining - 1;
- }
- }
- float PxFan::GetWindForce()
- {
- if(Removed || (IsActive() == false)) return 0.0;
- return 0.07 * FanForce * BaseSide;
- }
- void PxFan::UpdateBladePosition()
- {
- if(BaseSide < 0)
- BladePosX = PosX + BaseOffsetX - TurretScale*BladeOffsetX;
- else
- BladePosX = PosX + BaseOffsetX + TurretScale*BladeOffsetX;
- BladePosY = PosY + BaseOffsetY + TurretScale*BladeOffsetY;
- }
- void PxFan::Collide(CGObject* Obj, int type)
- {
- if(Obj->ClType == OC_Landscape && Planted == false)
- {
- SpX = 0;
- SpY = 0;
- Planted = true;
- return;
- }
- SpX = SpX * BounceMultiplierX;
- SpY = SpY * BounceMultiplierY;
- super;
- }
- // Applies blast damage
- // x, y : origin of the explosion
- // dmg : maximum damage the explosion should do
- void PxFan::TakeExplosionDamage(fixed x, fixed y, int dmg)
- {
- if(dmg == 0) return;
- float fdmg = dmg;
- float dx = PosX - x;
- float dy = PosY - y;
- float distsqr = dx*dx + dy*dy;
- float fdmgsqr = fdmg*fdmg*4.0;
- fdmg = (1.0 - distsqr/fdmgsqr) * fdmg;
- dmg = fdmg;
- if(dmg > 0) TakeDamage(0, dmg);
- }
- // Applies direct damage (without any further calculation)
- // type should be always 0 (10 is for percentage-based damage and is reserved to the Battle Axe)
- void PxFan::TakeDamage(int type, int dmg)
- {
- PrintMessage(type);
- if(type == 10)
- {
- fixed fdmg = dmg;
- fdmg = Health * fdmg / 100.0;
- dmg = fdmg;
- }
- Health -= dmg;
- }
- // Called when the object is destroyed
- void PxFan::Explode()
- {
- if(Removed) return;
- DoExplosion(PosX,PosY-20, ExplosionBlast, ExplosionDamage, 0, 0);
- SpeedDivider = 1000;
- SpX = 0.0;
- SpY = 0.0;
- GravityFactor = 0.0;
- IsMaterial = false;
- WIND_M->UpdateWind();
- }
- void PxFan::PushArrow()
- {
- if(NumArrows<6)
- {
- Arrows[NumArrows] = 0;
- NumArrows = NumArrows + 1;
- }
- }
- void PxFan::PopArrow()
- {
- if(NumArrows>0)
- {
- NumArrows = NumArrows - 1;
- for(int i = 0; i < NumArrows; i+=1)
- {
- Arrows[i] = Arrows[i+1];
- }
- }
- }
- // Renders the object
- void PxFan::Draw()
- {
- int baseX = PosX + BaseOffsetX;
- int baseY = PosY + BaseOffsetY;
- // Body
- if(BaseSide < 0)
- {
- AddSpriteEx(ZPlane+0.03, baseX, baseY, 262144 + SpriteBody, 0, 0, TurretScale);
- }
- else
- {
- AddSpriteEx(ZPlane+0.03, baseX, baseY, SpriteBody, 0, 0, TurretScale);
- }
- // Blades
- float r;
- float g;
- float b;
- int TeamColor;
- if (OwnerTeam < 1)
- {
- TeamColor = 0;
- }
- else
- {
- TeamColor = GetTeamColor(OwnerTeam) + 1;
- }
- if (TeamColor == 1)
- {
- r = 0.55;
- g = 0.15;
- b = 0.15;
- }
- else if (TeamColor == 2)
- {
- r = 0.15;
- g = 0.15;
- b = 0.55;
- }
- else if (TeamColor == 3)
- {
- r = 0.15;
- g = 0.55;
- b = 0.15;
- }
- else if (TeamColor == 4)
- {
- r = 0.50;
- g = 0.50;
- b = 0.15;
- }
- else if (TeamColor == 5)
- {
- r = 0.50;
- g = 0.15;
- b = 0.50;
- }
- else if (TeamColor == 6)
- {
- r = 0.15;
- g = 0.50;
- b = 0.50;
- }
- else
- {
- r = 0.4;
- g = 0.4;
- b = 0.4;
- }
- if(Sinking)
- {
- r = r * (90.0 / 255.0);
- g = g * (90.0 / 255.0);
- b = b * (240.0 / 255.0);
- ClearColorMod();
- }
- SetColorMod(RGB(r * 255.0, g * 255.0, b * 255.0), 6);
- float turretX = 0;
- float turretY = baseY+TurretScale*BladeOffsetY;
- local bladespr = SpriteBlade;
- if(AnimSpeed <= 0.0) bladespr = SpriteBladeIdle;
- local bladescale = TurretScale;
- if(FanMode > 0) bladescale = bladescale * 1.25;
- if(BaseSide < 0)
- {
- turretX = baseX-TurretScale*BladeOffsetX;
- AddSpriteEx(ZPlane+0.02, turretX, turretY, 262144 + bladespr, AnimCycle, 0, bladescale);
- }
- else
- {
- turretX = baseX+TurretScale*BladeOffsetX;
- AddSpriteEx(ZPlane+0.02, turretX, turretY, bladespr, AnimCycle, 0, bladescale);
- }
- ClearColorMod();
- // Arrows
- if(NumArrows>0)
- {
- CQuad q;
- local scale = TurretScale * ArrowScale;
- for(local i = 0; i < NumArrows; i+=1)
- {
- float dist = Arrows[i] * 0.1;
- float alpha = 255.0 * (-4 * dist * (dist - ArrowDistance)) / (ArrowDistance * ArrowDistance);
- FillSpriteQuad(&q, SpriteArrow, 0, 0);
- if(BaseSide < 0)
- {
- TransformQuad(&q, 0, -scale, scale, turretX + BaseSide * dist, turretY);
- }
- else
- {
- TransformQuad(&q, 0, scale, scale, turretX + BaseSide * dist, turretY);
- }
- for(int k=0 ; k<4 ; k+=1) q.v[k].color = ARGB(alpha,255,200,40);
- AddSpriteQ(ZPlane+0.01, &q, SpriteArrow, 0, 64);
- }
- }
- // Grate
- if(FanMode == 0)
- {
- if(BaseSide < 0)
- {
- AddSpriteEx(ZPlane, baseX-TurretScale*GrateOffsetX, baseY+TurretScale*GrateOffsetY, 262144 + SpriteGrate, 0, 0, TurretScale);
- }
- else
- {
- AddSpriteEx(ZPlane, baseX+TurretScale*GrateOffsetX, baseY+TurretScale*GrateOffsetY, SpriteGrate, 0, 0, TurretScale);
- }
- }
- }
- void PxFan::DoAnimation()
- {
- if(Removed) return;
- // Animating arrows
- if(NumArrows>0)
- {
- for(local i = 0; i < NumArrows; i+=1)
- {
- Arrows[i] += ArrowSpeed;
- }
- if(Arrows[0] >= (ArrowDistance*10)) PopArrow();
- }
- if(IsActive())
- {
- if(TargetAnimSpeed <= 0.0)
- {
- TargetAnimSpeed = MaxAnimSpeed;
- }
- if(NextArrow <= 0)
- {
- PushArrow();
- NextArrow = ArrowPeriod;
- }
- else
- {
- NextArrow = NextArrow - 1;
- }
- }
- else
- {
- if(TargetAnimSpeed > 0.0)
- {
- TargetAnimSpeed = 0.0;
- }
- }
- // Spinning blades
- if(AnimSpeed > (TargetAnimSpeed + AnimAccel))
- {
- AnimSpeed -= AnimAccel;
- }
- else if(AnimSpeed < (TargetAnimSpeed - AnimAccel))
- {
- AnimSpeed += AnimAccel;
- }
- else
- {
- AnimSpeed = TargetAnimSpeed;
- }
- AnimCycle = AnimCycle + AnimSpeed;
- if(AnimCycle >= 1.0) AnimCycle -= 1.0;
- }
- void PxFan::CheckBladeCollision()
- {
- if(FanMode == 0) return;
- if(IsActive() == false) return;
- if(NextBladeCooldown > 0)
- {
- NextBladeCooldown -= 1;
- return;
- }
- CGObject *obj;
- for(i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == this) continue;
- if(obj == NullObj) continue;
- if(MASK_FANBLADE_DMG->Check(BladePosX+5*BaseSide+6, BladePosY+14, obj->ColMask, obj->PosX, obj->PosY))
- {
- float damage = 0;
- bool hit = false;
- if(obj->ClType == OC_Worm)
- {
- local worm = CWorm(obj);
- // Reduce damage taken from consecutive hits to prevent worms from taking too much damage when stuck between a wall and a fan
- damage = DamagePerBladeHit - worm->FanDamageReducer;
- if(damage < 1)
- damage = 1;
- else
- worm->FanDamageReducer += DamageReductionPerHit;
- hit = true;
- }
- else if(obj->ClType == OC_Missile)
- {
- hit = true;
- }
- else if(obj->ClType == OC_Mine)
- {
- damage = DamagePerBladeHit;
- hit = true;
- }
- else if(obj is CMagnet)
- {
- damage = DamagePerBladeHit;
- hit = true;
- }
- else if(obj->ClType == OC_OilDrum)
- {
- damage = 100;
- hit = true;
- }
- else if(obj->ClType == OC_Crate)
- {
- damage = 100;
- hit = true;
- }
- if(hit)
- {
- float ang = RandomFloat(-1.57079, 1.57079);
- if(BaseSide < 0) ang += 3.14159;
- float ForceX = cos(ang) * BladeHitForce;
- float ForceY = -sin(ang) * BladeHitForce;
- if(damage > 0)
- {
- CMessageData msg;
- msg.params[0] = 0;
- msg.fparams[1] = PosX;
- msg.fparams[2] = PosY;
- msg.fparams[3] = ForceX;
- msg.fparams[4] = ForceY;
- msg.params[5] = damage;
- msg.params[6] = 0;
- obj->Message(this, M_GUNEXP, 1032, &msg);
- }
- else
- {
- obj->SpX += ForceX;
- obj->SpY += ForceY;
- }
- local p = new PxParticle(81, BladePosX, BladePosY);
- p->SetLifeTime(15);
- p->SetVelocity(0,0);
- p->SetStartAlpha(255);
- p->SetEndAlpha(255);
- PlayLocalSound(85, 5, 1.0, 1.0);
- TakeDamage(1, DamageTakenPerBladeHit);
- NextBladeCooldown = BladeCooldown;
- }
- }
- }
- }
- void PxFan::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- // Drawing operations are done here
- if(Type == M_DRAWQUEUE)
- {
- //if(Removed) return;
- if(Sinking) SetColorMod(RGB(90, 90, 240), 6);
- Draw();
- if(Sinking) ClearColorMod();
- // Recalculate Z plane periodically to make sure magnets are drawn properly when overlapping each other
- if(NextRecalcZPlane <= 0)
- {
- local matches = 0;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj == this) continue;
- if(obj is PxFan)
- {
- local fanobj = PxFan(obj);
- float dX = fanobj->PosX - PosX;
- float dY = fanobj->PosY - PosY;
- float r2 = dX*dX + dY*dY;
- if(r2 < 900.0)
- {
- if(fanobj->ZPlane == ZPlane)
- {
- fanobj->ZPlane = fanobj->ZPlane + 0.1;
- }
- matches = matches + 1;
- }
- }
- }
- if(matches == 0) ZPlane = 10;
- NextRecalcZPlane = 200;
- }
- else
- {
- NextRecalcZPlane = NextRecalcZPlane - 1;
- }
- return;
- }
- // Damage handling
- if(Removed==false)
- {
- if(Type == M_EXPLOSION)
- {
- TakeExplosionDamage(MData->fparams[1], MData->fparams[2], MData->params[4]);
- }
- if(Type == M_GUNEXP)
- {
- TakeDamage(MData->params[0], MData->params[5]);
- }
- }
- super;
- // This is done every frame (derp)
- if(Type == M_FRAME)
- {
- UpdateBladePosition();
- DoAnimation();
- if(Removed)
- {
- //if(NumArrows <= 0) Free(true);
- Free(true);
- return;
- }
- else
- {
- if(Sinking)
- {
- if(IsActive())
- {
- TurnsRemaining = 0;
- WIND_M->UpdateWind();
- }
- }
- if(IsActive() && (FanMode > 0))
- {
- CheckBladeCollision();
- }
- if(Health <= 0)
- {
- Explode();
- Removed = true;
- }
- }
- }
- }
- ///////////////////////////////////////////////////
- // CTurnGame overrides
- override void CTurnGame::SetCurrentTeam(int Team)
- {
- super;
- // Call OnTurnBegin on all fans
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj->ClType == OC_Worm)
- {
- // Reset damage reducer for all worms
- CWorm *w = CWorm(obj);
- w->FanDamageReducer = 0;
- }
- else if(obj is PxFan)
- {
- PxFan *fanobj = PxFan(obj);
- fanobj->OnTurnBegin(Team);
- }
- }
- // Resetting wind
- WIND_M->InitWind();
- WIND_M->UpdateWind();
- // Undoing permanent fan delays set up after placing a safe fan
- if(WEAPONINDEX_FAN >= 0)
- {
- local team = GetTeamColor(Team);
- GS->Info.Stores[team].Delay[WEAPONINDEX_FAN] = 0;
- }
- }
- ///////////////////////////////////////////////////
- // CWorm overrides
- override CWorm::CWorm(CObject* Parent, int aTeam, int aIndex, CWormParams* params)
- {
- super;
- FanForce = 3;
- FanMode = 0;
- FanDamageReducer = 0;
- }
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Fan"))
- {
- local ang = (1 - FireAngle) * 3.14159;
- if (TurnSide < 0)
- {
- ang = 6.28318 - ang;
- }
- CShootDesc SDesc;
- zero(&SDesc);
- local BaseForce = 0.3;
- SDesc.Team = WormTeam;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = SpX * 0.5 + TurnSide * BaseForce;
- SDesc.SpY = SpY * 0.5 - 0.15;
- new PxFan(GetObject(25, 0), &SDesc, FanForce, FanMode, TurnSide);
- //PrintMessage(GS->Info.Stores[WormTeam-1].Count[index]);
- if(FanMode == 0)
- {
- // Give the weapon a 1 turn delay so that you can't drop more than one fan in the same turn
- local index = Weap->GetWeaponIndex()+2;
- WEAPONINDEX_FAN = index;
- local team = GetTeamColor(WormTeam);
- GS->Info.Stores[team].Delay[index] = -1;
- }
- }
- else
- {
- super;
- }
- }
- void ShowFanMessage(int mode, int force)
- {
- if(mode)
- {
- ShowMessage(MakeNumberString("Fan, Force ", force, ", UNSAFE Mode"));
- }
- else
- {
- ShowMessage(MakeNumberString("Fan, Force ", force, ", SAFE Mode"));
- }
- }
- override void CWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if (CurWeapon->CheckName("Fan"))
- {
- local Team = CTeam(GetObject(21, WormTeam));
- Team->AllowSelectBounce = true;
- Team->AllowSelectDelay = true;
- if(FanMode == 0)
- {
- // Placing a fan in safe mode does not end turn
- CurWeapon->EndsTurn = false;
- }
- else
- {
- // Placing a fan in unsafe mode ends the current turn because it can potentially deal damage
- CurWeapon->EndsTurn = true;
- }
- }
- }
- else if (Type == M_SETBOUNCE)
- {
- if (CurWeapon->CheckName("Fan"))
- {
- if(MData->GetParameter(1) != WormNumber) return;
- local mode = MData->GetParameter(2);
- FanMode = mode;
- ShowFanMessage(FanMode, FanForce);
- return;
- }
- }
- else if(Type == M_SETDELAY)
- {
- if (CurWeapon->CheckName("Fan"))
- {
- if(MData->GetParameter(1) != WormNumber) return;
- local force = MData->GetParameter(2)+1;
- FanForce = force;
- ShowFanMessage(FanMode, FanForce);
- return;
- }
- }
- super;
- }
- PXS : Library Code :
- require utils;
- //#GLIDER_DEBUG
- //#GLIDER_NOANGLECONSTRAINT
- #WEAPON_GLIDER
- //////////////////////////
- // Global variables
- float GliderGravityFactor;
- float GliderWindFactor;
- float GliderFriction;
- float GliderMaxAngularVelocity;
- float GliderMaxTurningSpeed;
- float GliderAnimSpeed;
- float GliderRotationLerp;
- float GliderMoveAcceleration;
- CSprite* wormGliderSprite;
- CSprite* wormGliderBakSprite;
- //////////////////////////
- // Global initializations
- void paratest::FirstFrame()
- {
- // Tweaks
- GliderGravityFactor = 0.75;
- GliderWindFactor = 3.0;
- GliderFriction = 0.25;
- GliderMaxAngularVelocity = 0.06;
- GliderMaxTurningSpeed = 20.0;
- GliderAnimSpeed = 0.04;
- GliderRotationLerp = 0.03;
- GliderMoveAcceleration = 0.02;
- }
- void paratest::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("wgldlnk.png"); wormGliderSprite = LoadSprite(f, 10, 0);
- f = GetAttachment("wgldbak.png"); wormGliderBakSprite = LoadSprite(f, 6, 24);
- }
- //////////////////////////
- // CWormGlider
- CWormGlider::CWormGlider(CWorm *owner)
- {
- GliderAnimCycle = 0.0;
- GliderAng = 0.0;
- GliderTargetAng = 0.0;
- ParaSpX = 0.0;
- ParaSpY = 0.0;
- Deployed = false;
- Enabled = false;
- Owner = owner;
- PRegister(&Owner);
- // Angle system used for the Hang-Glider
- // -pi/2
- // -
- //
- // 0 <-----|
- //
- // +
- // +pi/2
- //
- // positive angle = facing down
- // negative angle = facing up
- }
- void CWormGlider::OnStartGliding()
- {
- GliderAng = 0.0;
- GliderTargetAng = 0.0;
- GliderAnimCycle = 0.0;
- }
- void CWormGlider::OnStopGliding()
- {
- GliderAng = 0.0;
- GliderTargetAng = 0.0;
- GliderAnimCycle = 0.0;
- }
- void CWormGlider::Think()
- {
- // Owner was deleted, don't do anything
- if(Owner == NullObj)
- {
- PUnregister(&Owner);
- return;
- }
- // Which kind of parachute is currently used?
- if(Owner->ObjState != WS_PARACHUTE)
- {
- if(Owner->CurWeapon->CheckName("Hang-Glider"))
- {
- Enabled = true;
- }
- else if(Owner->CurWeapon->CheckName("Parachute"))
- {
- Enabled = false;
- }
- }
- if(Owner->ObjState == WS_PARACHUTE)
- {
- if(Enabled)
- {
- // Worm just entered parachute state while having the Hang-Glider equipped, start the physics overrides
- if(Deployed == false)
- {
- Deployed = true;
- OnStartGliding();
- }
- // Invisible animation (prevents the worm from being drawn using the default method)
- Owner->Anim->Reset();
- Owner->Anim->SetAnimEx(136, 0.0);
- }
- else
- {
- // Using regular Parachute, don't do anything
- return;
- }
- }
- else
- {
- // Worm left parachute state, stop the physics overrides
- if(Deployed)
- {
- Deployed = false;
- OnStopGliding();
- }
- // Always keep track of the worm's current velocity (so it is transmitted to the glider when it becomes deployed)
- ParaSpX = Owner->SpX;
- ParaSpY = Owner->SpY;
- return;
- }
- ////////////////////////////////////
- // Main physics calculations
- // Calculating up and forward relative vectors
- float ang;
- if(Owner->TurnSide < 0)
- {
- ang = GliderAng;
- }
- else
- {
- ang = 3.141593 - GliderAng;
- }
- float ForwardX = -cos(ang);
- float ForwardY = sin(ang);
- float UpX;
- float UpY;
- if(Owner->TurnSide < 0)
- {
- UpX = -ForwardY;
- UpY = ForwardX;
- }
- else
- {
- UpX = ForwardY;
- UpY = -ForwardX;
- }
- // Applying gravity
- ParaSpY = ParaSpY + GS->env->Gravity * GliderGravityFactor;
- // Applying wind
- float WindVel = UpX * GS->env->Wind * GliderWindFactor;
- ParaSpX = ParaSpX + WindVel * UpX;
- ParaSpY = ParaSpY + WindVel * UpY;
- // Applying air resistance
- float UpVel = ParaSpX * UpX + ParaSpY * UpY;
- ParaSpX = ParaSpX - UpX * UpVel * GliderFriction;
- ParaSpY = ParaSpY - UpY * UpVel * GliderFriction;
- // Don't go backwards
- //if(ParaSpX * Owner->TurnSide < 0)
- //{
- // ParaSpX = 0;
- //}
- // Calculating new glider angle based on current speed
- if(Owner->TurnSide < 0)
- {
- ang = atan2(ParaSpY, -ParaSpX);
- }
- else
- {
- ang = atan2(ParaSpY, ParaSpX);
- }
- // Normalize
- ang = NormalizeAngle(ang);
- // Clamp to approx. [-80° ; 80°] (don't fly straight down when nose-diving)
- if(#GLIDER_NOANGLECONSTRAINT) { }
- else
- {
- if(ang > 1.5) ang = 1.5;
- if(ang < -1.5) ang = -1.5;
- }
- GliderTargetAng = ang;
- // Approach the target angle
- GliderAng = LerpAngle(GliderRotationLerp, GliderAng, GliderTargetAng);
- if(#GLIDER_DEBUG)
- {
- // DEBUG1 : GliderAng
- Debug1X = Owner->PosX + 40*ForwardX;
- Debug1Y = Owner->PosY + 40*ForwardY;
- // DEBUG2 : GliderTargetAng
- if(Owner->TurnSide < 0)
- {
- ang = GliderTargetAng;
- }
- else
- {
- ang = 3.141593 - GliderTargetAng;
- }
- ForwardX = -cos(ang);
- ForwardY = sin(ang);
- Debug2X = Owner->PosX + 40*ForwardX;
- Debug2Y = Owner->PosY + 40*ForwardY;
- // END DEBUG
- }
- // Animation
- GliderAnimCycle = GliderAnimCycle + GliderAnimSpeed;
- if(GliderAnimCycle >= 1.0) GliderAnimCycle = 1.0;
- // Going to hit an obstacle, stop gliding
- int hitX;
- int hitY;
- if(TraceMask(Owner, Owner->ColMask, Owner->PosX, Owner->PosY, Owner->PosX + 1.1 * ParaSpX, Owner->PosY + 1.1 * ParaSpY, 4332670, &hitX, &hitY) != NullObj)
- {
- Owner->SetState(WS_AFTERROPE);
- }
- // Update the worm's velocity
- Owner->SpX = ParaSpX;
- Owner->SpY = ParaSpY;
- }
- void CWormGlider::Render()
- {
- if(Deployed)
- {
- if(Owner->TurnSide < 0)
- {
- Owner->AddSpriteEx(6, Owner->PosX, Owner->PosY, wormGliderSprite->Index, GliderAnimCycle, -GliderAng, 1.0);
- }
- else
- {
- Owner->AddSpriteEx(6, Owner->PosX, Owner->PosY, wormGliderSprite->Index + 262144, GliderAnimCycle, GliderAng, 1.0);
- }
- if(#GLIDER_DEBUG)
- {
- Owner->AddSpriteEx(7, Debug1X, Debug1Y, 2, 0, 0, 1);
- Owner->AddSpriteEx(7.1, Debug2X, Debug2Y, 3, 0, 0, 1);
- }
- }
- }
- void CWormGlider::Move(EMType Type)
- {
- if(Type == M_PUP)
- {
- // Rotate up
- float vel = sqrt(ParaSpX*ParaSpX + ParaSpY*ParaSpY) / GliderMaxTurningSpeed;
- if(vel > 1.0) vel = 1.0;
- GliderAng -= GliderMaxAngularVelocity * vel;
- if(#GLIDER_NOANGLECONSTRAINT) { }
- else if(GliderAng < -1.5)
- {
- GliderAng = -1.5;
- }
- }
- else if(Type == M_PDOWN)
- {
- // Rotate down
- float vel = sqrt(ParaSpX*ParaSpX + ParaSpY*ParaSpY) / GliderMaxTurningSpeed;
- if(vel < 0.5) vel = 0.5;
- if(vel > 1.0) vel = 1.0;
- GliderAng += GliderMaxAngularVelocity * vel;
- if(#GLIDER_NOANGLECONSTRAINT) { }
- else
- if(GliderAng > 1.5)
- {
- GliderAng = 1.5;
- }
- }
- if(Type == M_PLEFT)
- {
- // Left acceleration
- ParaSpX -= GliderMoveAcceleration;
- }
- else if(Type == M_PRIGHT)
- {
- // Right acceleration
- ParaSpX += GliderMoveAcceleration;
- }
- }
- ///////////////////////////
- // CWorm overrides
- override CWorm::CWorm(CObject* Parent, int aTeam, int aIndex, CWormParams* params)
- {
- super;
- Glider = new CWormGlider(this);
- }
- override void CWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- Glider->Think();
- }
- if(Type == M_DRAWQUEUE)
- {
- if(Glider->Deployed)
- {
- Glider->Render();
- //return;
- }
- }
- if(Type == M_PUP || Type == M_PDOWN || Type == M_PLEFT || Type == M_PRIGHT)
- {
- if(Glider->Deployed)
- {
- Glider->Move(Type);
- }
- }
- super;
- }
- ///////////////////////////////////////////////////
- // CSpriteAnim overrides
- override void CSpriteAnim::SetAnimEx(int sindex, fixed frame)
- {
- // Make sure the game has actually started (otherwise GetCurrentWorm would crash the game due to Root not existing)
- if(GS->Tick >= 1)
- {
- // If we belong to the current worm
- CWorm *w = GetCurrentWorm();
- if(w != NullObj && w->Anim == this)
- {
- if(sindex == 289 && w->Glider->Enabled) // Glider landing animation
- {
- super(wormGliderBakSprite->Index, frame);
- return;
- }
- }
- }
- super;
- }
- PXS : Library Code :
- CQuad __BQ;
- int __BN;
- fixed __BZ;
- fixed __BF;
- int __BT;
- int __BB;
- CObject *__BO;
- CTexBeamPoint::CTexBeamPoint()
- {
- x = 0.0;
- y = 0.0;
- dx = 0.0;
- dy = 0.0;
- texcoord = 0.0;
- color = 0;
- }
- void CTexBeamPoint::Copy(CTexBeamPoint *dest)
- {
- dest->x = x;
- dest->y = y;
- dest->dx = dx;
- dest->dy = dy;
- dest->texcoord = texcoord;
- dest->color = color;
- }
- void CTexBeamPoint::RenderBeamSection(CTexBeamPoint *target)
- {
- __BQ.blend = __BB;
- __BQ.tex = __BT;
- __BQ.v[0].x = x + dx;
- __BQ.v[0].y = y + dy;
- __BQ.v[0].z = __BZ;
- __BQ.v[0].tx = texcoord;
- __BQ.v[0].ty = 0.0;
- __BQ.v[0].color = color;
- __BQ.v[3].x = x - dx;
- __BQ.v[3].y = y - dy;
- __BQ.v[3].z = __BZ;
- __BQ.v[3].tx = texcoord;
- __BQ.v[3].ty = 1.0;
- __BQ.v[3].color = color;
- __BQ.v[1].x = target->x + target->dx;
- __BQ.v[1].y = target->y + target->dy;
- __BQ.v[1].z = __BZ;
- __BQ.v[1].tx = target->texcoord;
- __BQ.v[1].ty = 0.0;
- __BQ.v[1].color = target->color;
- __BQ.v[2].x = target->x - target->dx;
- __BQ.v[2].y = target->y - target->dy;
- __BQ.v[2].z = __BZ;
- __BQ.v[2].tx = target->texcoord;
- __BQ.v[2].ty = 1.0;
- __BQ.v[2].color = target->color;
- __BO->AddSpriteQ(__BZ, &__BQ, __BT, __BF, 64);
- }
- CTexBeamPoint *__BP0;
- CTexBeamPoint *__BP1;
- CTexBeamPoint *__BP2;
- float __BW0;
- void texbeam::InitGraphic()
- {
- __BP0 = new CTexBeamPoint();
- __BP1 = new CTexBeamPoint();
- __BP2 = new CTexBeamPoint();
- }
- void StartTexturedBeam(CObject *parent, fixed z, int tex, fixed frame, int blendmode)
- {
- __BO = parent;
- __BN = 0;
- __BZ = z;
- __BT = tex;
- __BF = frame;
- __BB = blendmode;
- }
- void TexturedBeamPoint(float x, float y, float width, float texcoord, int color)
- {
- __BP0->x = x;
- __BP0->y = y;
- __BP0->texcoord = texcoord;
- __BP0->color = color;
- if(__BN > 0)
- {
- float dx = __BP0->x - __BP1->x;
- float dy = __BP0->y - __BP1->y;
- float d = sqrt(dx*dx+dy*dy);
- // todo: exception handling for two successive beam points at the exact same position. (d=0)
- __BP0->dx = -width * dy / d;
- __BP0->dy = width * dx / d;
- if(__BN == 1)
- {
- __BP1->dx = -__BW0 * dy / d;
- __BP1->dy = __BW0 * dx / d;
- }
- else
- {
- __BP1->dx = (__BP0->dx + __BP2->dx) / 2.0;
- __BP1->dy = (__BP0->dy + __BP2->dy) / 2.0;
- __BP2->RenderBeamSection(__BP1);
- }
- }
- __BN += 1;
- __BP1->Copy(__BP2);
- __BP0->Copy(__BP1);
- __BW0 = width;
- }
- void EndTexturedBeam()
- {
- if(__BN > 0)
- {
- __BP2->RenderBeamSection(__BP1);
- }
- }
- PXS : Library Code :
- require utils, pxparticles, pxtexbeam;
- /////////////////////////////////////////
- // Uses custom message type 1000
- // Sent to objects when hit by lightning
- // params[0] : Lightning type (0 : lightning strike, 1 : tazer)
- // params[1] : Owner team
- CSprite* lightningBeamSprite;
- CSprite* lightningGlowSprite;
- CSoundFile* lightningStartSound;
- CSoundFile* lightningHitSound;
- CColMask* LIGHTNING_HITMASK;
- int LightningR;
- int LightningG;
- int LightningB;
- // Main beam : 17 divisions
- // Sub-beams : 6 * 9 divisions
- // = 71
- //float NoiseTable[71];
- // Main beam : 9 divisions
- // Sub-beams : 6 * 9 divisions
- // = 63
- float NoiseTable[63];
- // Generate this table randomly to decide which point of the main beam will have a sub beam attached to it
- //bool AttachSubBeam[17];
- bool AttachSubBeam[9];
- PxDeadWormManager : CObject;
- PxDeadWormManager *DW_M;
- void lightningstrike::FirstFrame()
- {
- CFile *f;
- f = GetAttachment("lightningthund.wav"); lightningStartSound = new CSoundFile(f);
- f = GetAttachment("lightninghit.wav"); lightningHitSound = new CSoundFile(f);
- LIGHTNING_HITMASK = new CColMask(12, 12, MakeCircleMask(12));
- DW_M = new PxDeadWormManager();
- //LightningR = 160;
- //LightningG = 220;
- //LightningB = 255;
- LightningR = 120;
- LightningG = 140;
- LightningB = 255;
- }
- void lightningstrike::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("lightning_beam.png"); lightningBeamSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("lightning_glow.png"); lightningGlowSprite = LoadSprite(f, 1, 0);
- }
- ///////////////////////////////////////////////////
- // PxDeadWorm (used to resurrect worms from graves)
- PxDeadWorm : CObject
- PxDeadWormManager::PxDeadWormManager()
- {
- super(Root, GS);
- }
- PxDeadWorm* PxDeadWormManager::DeadWormFromGrave(CGObject *grave)
- {
- PxDeadWorm *deadworm;
- for(int i=0 ; i<Childs.Count ; i+=1)
- {
- deadworm = PxDeadWorm(Childs.Objs[i]);
- if(deadworm == PxDeadWorm(NullObj)) continue;
- if(deadworm->GraveObj == grave)
- {
- return deadworm;
- }
- }
- return PxDeadWorm(NullObj);
- }
- PxDeadWorm::PxDeadWorm(CWorm *worm, CGObject *grave)
- {
- super(DW_M, GS);
- GraveObj = grave;
- PRegister(&GraveObj);
- WormNumber = worm->WormNumber;
- WormTeam = worm->WormTeam;
- WormName = worm->GetName();
- ResurrectedWorm = CWorm(NullObj);
- RemoveMe = false;
- }
- void PxDeadWorm::Resurrect(int health)
- {
- if(RemoveMe) return;
- if(GraveObj == CGObject(NullObj)) return;
- ResurrectedWorm = RessurectWormEx(WormNumber, WormTeam, 0, 0, WormName, health);
- ResurrectedWorm->PosX = GraveObj->PosX;
- ResurrectedWorm->PosY = GraveObj->PosY-5;
- ResurrectedWorm->ResurrectedByLightning = true;
- GraveObj->Free(true);
- PUnregister(&GraveObj);
- RemoveMe = true;
- }
- void PxDeadWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if(RemoveMe)
- {
- if(ResurrectedWorm != CWorm(NullObj))
- {
- ResurrectedWorm->ResurrectedByLightning = false;
- }
- Free(true);
- return;
- }
- if(GraveObj == CGObject(NullObj))
- {
- PUnregister(&GraveObj);
- RemoveMe = true;
- return;
- }
- }
- if(Type == M_DRAWQUEUE)
- {
- return;
- }
- super;
- }
- ///////////////////////////////////////////////////
- // PxLightningStrike
- PxLightningStrike : CObject;
- PxLightningStrike::PxLightningStrike(CObject* Parent, CShootDesc* Desc)
- {
- super(Parent, GS);
- ClType = OC_AirStrike;
- // Lightning parameters
- LightningPitch = 30.0;
- LightningMaxDistance = 300.0;
- LightningMinY = -270;
- // Calculate the lightning strike's starting position (where the cloud will appear)
- // and ending position (where the lightning will strike)
- float ang = (LightningPitch * 3.141593) / 180.0;
- DirX = sin(ang);
- DirY = cos(ang);
- if(Desc->SpX < 0) DirX = -DirX;
- // Perform a projection on y = LightningMinY (maximum height at which the lightning cloud can appear)
- float y = LightningMinY;
- float x = Desc->AddX - (Desc->AddY - y) * (DirX / DirY);
- StartX = int(x);
- StartY = int(y);
- LightningHitLand = true;
- // Trace down and get the exact strike position
- int hitX;
- int hitY;
- int tracemask = CMASK_TERRAIN
- | CMASK_WORM_ON_TERRAIN
- | CMASK_WORM_USING_WEAPON
- | CMASK_WORM_IN_MIDAIR
- | CMASK_WORM_ON_ROPE
- | CMASK_WORM_FROZEN
- | CMASK_GASCANISTER
- | CMASK_MINE
- | CMASK_CRATE
- | CMASK_DONORCARD
- | CMASK_GRAVESTONE
- | CMASK_OTHERWEAPON
- | CMASK_OILDRUM;
- if(TraceLine(this, StartX, StartY, StartX + 10000 * DirX, StartY + 10000 * DirY, tracemask, &hitX, &hitY) == NullObj)
- {
- // Didn't hit anything, just spawn the cloud high in the sky and make it strike some arbitrary point
- x = StartX + LightningMaxDistance * DirX;
- y = StartY + LightningMaxDistance * DirY;
- hitX = x;
- hitY = y;
- LightningHitLand = false;
- }
- else
- {
- if(hitY - LightningMaxDistance * DirY > StartY)
- {
- // Hit something but it's too far away from the cloud
- // Move the cloud down accordingly to the hit position
- x = hitX - LightningMaxDistance * DirX;
- y = hitY - LightningMaxDistance * DirY;
- StartX = x;
- StartY = y;
- }
- }
- EndX = hitX;
- EndY = hitY;
- // Must be a multiple of 2 + 1, because we're generating fractal noise
- // this should have been used to allocate the noise table but due to an issue with EAX,
- // the noise table has been declared as a global variable (see line 15)
- //NoiseDivs = (1 << 4) + 1; // 17
- NoiseDivs = (1 << 3) + 1; // 9
- SubNoiseDivs = (1 << 3) + 1; // 9
- MaxSubBeams = (NoiseDivs * 2) / 3;
- GenerateNoise();
- // Timer stuff
- CloudGenerateTimer = 0;
- LightningHitDelay = 150;
- LightningTime = 16;
- PostLightningTime = 60;
- // Internal states
- Dead = false;
- IsFirstFrame = true;
- OwnerTeam = Desc->Team;
- GroundGlowSize = 0.5;
- }
- // Calculates fractal noise from NoiseTable[offset] to NoiseTable[offset+divs-1]
- void PxLightningStrike::CalcNoise(int offset, int divs, float scale, float start, float end)
- {
- int i;
- int k = divs;
- int l = k >> 1;
- for(i=0 ; i<divs ; i+=1) NoiseTable[offset+i] = 0.0;
- NoiseTable[offset] = start;
- NoiseTable[offset+divs-1] = end;
- while(l > 0)
- {
- for(i=l ; i<divs ; i+=k)
- {
- NoiseTable[offset+i] = (NoiseTable[offset+i-l] + NoiseTable[offset+i+l]) * 0.5 + RandomFloat(-scale, scale);
- }
- k = l;
- l = k >> 1;
- }
- }
- // Fills NoiseTable with fractal noise (1 main beam + 6 secondary beams), and generates the secondary beam attachment table
- void PxLightningStrike::GenerateNoise()
- {
- int i;
- CalcNoise(0, NoiseDivs, 1.0, 0.0, 0.0);
- for(i=0 ; i<NoiseDivs ; i+=1) AttachSubBeam[i] = false;
- for(i=0 ; i<MaxSubBeams ; i+=1) AttachSubBeam[RandomInt(1,16)] = true;
- for(i=0 ; i<MaxSubBeams ; i+=1)
- {
- float offset = RandomFloat(2.0,6.0);
- if(RandomInt(0,1) == 0) offset = -offset;
- CalcNoise(NoiseDivs + SubNoiseDivs * i, SubNoiseDivs, 0.5, 0.0, offset);
- }
- GroundGlowSize = RandomFloat(0.5,0.8);
- }
- // Renders one lightning beam using data previously generated by GenerateNoise
- void PxLightningStrike::RenderBeam(int offset, int divs, float width, float endwidth, float scale, float x1, float y1, float x2, float y2, float glowalpha)
- {
- float fraction;
- float x;
- float y;
- float d = divs - 1;
- int i;
- float j;
- float dx = x2-x1;
- float dy = y2-y1;
- float dd = sqrt(dx*dx+dy*dy);
- dx = dx / dd;
- dy = dy / dd;
- StartTexturedBeam(this, 11, lightningBeamSprite->Index, 0.0, 1);
- CQuad q;
- for(i=0 ; i<divs ; i+=1)
- {
- j = i;
- fraction = j / d;
- x = Lerp(fraction, x1, x2) + scale * dy * NoiseTable[offset+i];
- y = Lerp(fraction, y1, y2) - scale * dx * NoiseTable[offset+i];
- float w = Lerp(fraction, width, endwidth);
- float r = LightningR * glowalpha * (1.0 - fraction);
- float g = LightningG * glowalpha * (1.0 - fraction);
- float b = LightningB * glowalpha * (1.0 - fraction);
- TexturedBeamPoint(x, y, w, fraction, RGB(LightningR, LightningG, LightningB));
- FillSpriteQuad(&q, lightningGlowSprite->Index, 0, 0);
- TransformQuad(&q, 0, 0.5, 0.5, x, y);
- q.blend = 1;
- for(int k=0 ; k<4 ; k+=1) q.v[k].color = RGB(r,g,b);
- AddSpriteQ(9.9, &q, lightningGlowSprite->Index, 0, 64);
- }
- EndTexturedBeam();
- }
- // Renders the main lightning beam and its secondary beams
- void PxLightningStrike::RenderLightning()
- {
- if(LightningHitDelay >= 8) return;
- int divs = NoiseDivs;
- float endx = EndX;
- float endy = EndY;
- if(LightningHitDelay > 0)
- {
- float fr = (8.0 - LightningHitDelay) / 8.0;
- float fdivs = NoiseDivs * fr;
- divs = fdivs;
- endx = Lerp(fr, StartX, EndX);
- endy = Lerp(fr, StartY, EndY);
- }
- RenderBeam(0, divs, 35.0, 3.0, 15.0, StartX, StartY, endx, endy, 1.0);
- float fraction;
- float x;
- float y;
- float d = divs - 1;
- int i;
- float j;
- int subBeam = 0;
- for(i=0 ; i<divs ; i+=1)
- {
- if(AttachSubBeam[i])
- {
- j = i;
- fraction = j / d;
- x = Lerp(fraction, StartX, endx) + 10.0 * DirY * NoiseTable[i];
- y = Lerp(fraction, StartY, endy) - 10.0 * DirX * NoiseTable[i];
- RenderBeam(NoiseDivs + SubNoiseDivs * subBeam, SubNoiseDivs, Lerp(fraction, 10.0, 1.0), 0.1, 15.0 * (1.0 - fraction), x, y,
- x + DirX * 100.0 * (1.0 - fraction), y + DirY * 100.0 * (1.0 - fraction), 0.5 * (1.0 - fraction));
- subBeam = subBeam + 1;
- }
- }
- CQuad q;
- FillSpriteQuad(&q, lightningGlowSprite->Index, 0, 0);
- TransformQuad(&q, 0, 1.8, 1.8, StartX+10*DirX, StartY+10*DirY);
- q.blend = 1;
- for(i=0 ; i<4 ; i+=1) q.v[i].color = RGB(LightningR,LightningG,LightningB);
- AddSpriteQ(9.9, &q, lightningGlowSprite->Index, 0, 64);
- if(LightningHitDelay <= 0 && LightningHitLand)
- {
- FillSpriteQuad(&q, lightningGlowSprite->Index, 0, 0);
- TransformQuad(&q, 0, GroundGlowSize, GroundGlowSize, EndX, EndY);
- q.blend = 1;
- for(i=0 ; i<4 ; i+=1) q.v[i].color = RGB(LightningR,LightningG,LightningB);
- AddSpriteQ(9.9, &q, lightningGlowSprite->Index, 0, 64);
- }
- }
- // Applies the lightning strike effect to a particular object
- void PxLightningStrike::LightningHit(CGObject *obj)
- {
- if(#WEAPON_MAGNET)
- {
- if(obj is CMagnet)
- {
- // Recharge magnets
- local mag = CMagnet(obj);
- mag->Recharge();
- return;
- }
- }
- if(#WEAPON_BOWLINGBALL)
- {
- if(obj is CBowlingBall)
- {
- // Overcharge bowling balls
- local ball = CBowlingBall(obj);
- ball->Zap(0);
- return;
- }
- }
- if(#WEAPON_FAN)
- {
- if(obj is PxFan)
- {
- // Recharge magnets
- local fanobj = PxFan(obj);
- fanobj->Recharge();
- return;
- }
- }
- if(#WEAPON_KSENTRY)
- {
- if(obj is PxSentryGun)
- {
- // Changes sentry teams
- local sentry = PxSentryGun(obj);
- sentry->OwnerTeam = OwnerTeam;
- sentry->TurretActive = false;
- return;
- }
- }
- if(obj->ClType == OC_Mine)
- {
- // Trigger mines
- local mine = CMine(obj);
- // If the mine is not a special mine, can be triggered, and has not been triggered yet
- if(mine->Radius > 0 && mine->Active == 0 && mine->Prefuse <= 0)
- {
- // If the mine has a random timer
- if(mine->Fuse < 0)
- {
- // Give it a random fuse time (between 1 and 5)
- mine->Fuse = RandomInt(1000, 5000);
- }
- // Trigger the mine
- mine->Active = 1;
- mine->nPulses = mine->Fuse / 250;
- }
- }
- else if(obj->ClType == OC_OilDrum || obj->ClType == OC_Crate)
- {
- // Blow up oil drums and crates
- CMessageData msg;
- msg.params[0] = 0;
- msg.fparams[1] = EndX;
- msg.fparams[2] = EndY;
- msg.fparams[3] = 0.0;
- msg.fparams[4] = 0.0;
- msg.params[5] = 100;
- msg.params[6] = 0;
- obj->Message(this, M_GUNEXP, 1032, &msg);
- }
- else if(obj->ClType == OC_Worm)
- {
- // Heal worms
- local worm = CWorm(obj);
- if(worm->ResurrectedByLightning == false)
- {
- int health = GS->Info.GetWormHealth(worm->WormTeam, worm->WormNumber);
- GS->Info.SetWormHealth(worm->WormTeam, worm->WormNumber, health + 25);
- }
- }
- else if(obj->ClType == OC_Cross)
- {
- // Resurrect worms from their grave
- local deadworm = DW_M->DeadWormFromGrave(obj);
- if(deadworm != PxDeadWorm(NullObj))
- {
- deadworm->Resurrect(10);
- }
- else
- {
- ShowMessage("Grave has no bound worm, could not resurrect!");
- }
- }
- // Allows any object to define its own custom behaviour
- //CMessageData msg;
- //msg.params[0] = 0;
- //msg.params[1] = OwnerTeam;
- //obj->Message(this, EMType(1000), 1032, &msg);
- }
- // Performs a mask test and applies the lightning strike effect to all detected objects
- void PxLightningStrike::DoLightningStrike()
- {
- CGObject *obj;
- for(int i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == NullObj) continue;
- if(LIGHTNING_HITMASK->Check(EndX, EndY, obj->ColMask, obj->PosX, obj->PosY))
- {
- LightningHit(obj);
- }
- }
- }
- void PxLightningStrike::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- PxParticle *p;
- if(Dead)
- {
- Free(true);
- return;
- }
- if(IsFirstFrame)
- {
- lightningStartSound->Play(1.0, 0.0, false);
- IsFirstFrame = false;
- }
- if(LightningTime > 0)
- {
- if(LightningHitDelay <= 0)
- {
- GenerateNoise();
- if(LightningHitLand)
- {
- p = new PxParticle(lightningGlowSprite->Index, EndX, EndY);
- p->SetBlendMode(1);
- p->SetLifeTime(50);
- p->SetRandomVelocity(1.0, 3.0);
- p->SetAirResistance(0.0);
- p->GravityFactor(1.0);
- p->SetAlpha(255);
- p->SetColor(LightningR, LightningG, LightningB);
- p->SetStartSize(0.1, 0.1);
- p->SetEndSize(0.01, 0.01);
- }
- LightningTime = LightningTime - 1;
- if(LightningHitLand && LightningTime <= 0)
- {
- DoLightningStrike();
- }
- }
- else
- {
- LightningHitDelay = LightningHitDelay - 1;
- if(LightningHitDelay == 0)
- {
- lightningHitSound->Play(1.0, 0.0, false);
- }
- }
- }
- else
- {
- PostLightningTime = PostLightningTime - 1;
- if(PostLightningTime <= 0)
- {
- Dead = true;
- }
- }
- if(CloudGenerateTimer <= 0)
- {
- float xvel;
- float yvel;
- // Core clouds
- if(LightningTime > 0)
- {
- p = new PxParticle(618, StartX, StartY);
- p->SetAnimSpeed(0.02);
- p->SetLifeTime(100);
- xvel = RandomFloat(-1.0, 1.0);
- yvel = 1.0 - (xvel * xvel);
- p->SetVelocity(16.0 * xvel, RandomFloat(-8.0, 1.0) * yvel);
- p->SetAirResistance(0.3);
- p->SetStartAlpha(0);
- p->SetEndAlpha(255);
- p->SetStartSize(1.2, 1.2);
- p->SetEndSize(0.6, 0.6);
- p->SetStartColor(45,40,60);
- p->SetEndColor(45,40,60);
- }
- // Surrounding clouds
- p = new PxParticle(618, StartX, StartY);
- p->SetAnimSpeed(0.02);
- p->SetLifeTime(140);
- xvel = RandomFloat(-1.0, 1.0);
- yvel = 1.0 - (xvel * xvel);
- p->SetVelocity(16.0 * xvel, RandomFloat(-8.0, 1.0) * yvel);
- p->SetAirResistance(0.15);
- p->SetStartAlpha(0);
- p->SetEndAlpha(255);
- p->SetStartSize(1.0, 1.0);
- p->SetEndSize(0.01, 0.01);
- p->SetStartColor(45,40,60);
- p->SetEndColor(45,40,60);
- CloudGenerateTimer = 2;
- }
- CloudGenerateTimer = CloudGenerateTimer - 1;
- }
- if(Type == M_DRAWQUEUE)
- {
- if(LightningTime <= 0) return;
- //AddSprite(10, StartX, StartY, 0, 2, 0.0);
- //AddSprite(10, EndX, EndY, 0, 2, 0.0);
- RenderLightning();
- return;
- }
- super;
- }
- ///////////////////////////////////////////////////
- // CWorm overrides
- override CWorm::CWorm(CObject* Parent, int aTeam, int aIndex, CWormParams* params)
- {
- super;
- ResurrectedByLightning = false;
- }
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Lightning Strike"))
- {
- new PxLightningStrike(GetObject(25, 0), Desc);
- }
- else
- {
- super;
- }
- }
- override void CWorm::Free(bool freeMem)
- {
- CGObject *obj;
- for(int i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == NullObj) continue;
- if(obj->ClType == OC_Cross)
- {
- if(obj->PosX == PosX && obj->PosY == PosY)
- {
- new PxDeadWorm(this, obj);
- break;
- }
- }
- }
- super;
- }
- PXS : Library Code :
- require utils, pxparticles;
- PxBulletDesc::PxBulletDesc()
- {
- Damage = 10;
- Push = 2;
- Count = 1;
- Spread = 0.0;
- Flags = 4332670;
- Team = 0;
- }
- void FireBullets(CObject *parent, CShootDesc *sdesc, PxBulletDesc *bdesc)
- {
- float ang = atan2(sdesc->SpY, sdesc->SpX);
- float radiusSqr = bdesc->Damage * bdesc->Damage;
- float spread = bdesc->Spread;
- int hitX;
- int hitY;
- CGObject *hitObject;
- int holeSize = bdesc->Damage;
- if(holeSize < 5) holeSize = 5;
- for(int i=0 ; i < bdesc->Count ; i+=1)
- {
- float a;
- if(spread == 0.0) a = ang;
- else a = ang + spread * RandomFloat(-1.0, 1.0);
- float dirX = cos(a);
- float dirY = sin(a);
- float endX = sdesc->X + dirX * 10000.0;
- float endY = sdesc->Y + dirY * 10000.0;
- hitObject = TraceLine(parent, sdesc->X, sdesc->Y, endX, endY, bdesc->Flags, &hitX, &hitY);
- if(hitObject != NullObj)
- {
- GG->land->MakeHole(holeSize, hitX, hitY);
- // Hit effect
- PxParticle *p;
- if(hitObject->ClType == OC_Worm)
- {
- p = new PxParticle(118, hitX, hitY);
- p->SetVelocity(0, 1);
- }
- else
- {
- p = new PxParticle(116, hitX, hitY);
- p->SetVelocity(0, 0);
- }
- p->SetLifeTime(30);
- p->GravityFactor(0);
- p->SetAlpha(255);
- p->SetSize(1, 1);
- p->SetColor(255,255,255);
- for(int j=0 ; j<5 ; j+=1)
- {
- p = new PxParticle(131, hitX, hitY);
- p->SetLifeTime(50);
- p->SetRandomVelocity(2.0, 3.5);
- p->GravityFactor(-3);
- p->SetAirResistance(0.2);
- p->SetAlpha(255);
- p->SetSize(0.5, 0.5);
- p->SetColor(255,255,255);
- p->SetMotionRandomness(1.0);
- }
- // Custom damage falloff
- CMessageData msg;
- for(i = 0; i < Env->Objs.Count; i += 1)
- {
- obj = CGObject(Env->Objs.Objs[i]);
- if(obj == NullObj) continue;
- if(obj->ClType == OC_Landscape) continue;
- float dx = obj->PosX - hitX;
- float dy = obj->PosY - hitY;
- float dsqr = dx*dx+dy*dy;
- if(obj == hitObject || dsqr <= radiusSqr)
- {
- float fraction;
- if(obj == hitObject)
- {
- fraction = 1.0;
- }
- else
- {
- fraction = 1.0 - dsqr / (3*radiusSqr);
- if(fraction > 1.0) fraction = 1.0;
- }
- float dmg = fraction * bdesc->Damage;
- float force = fraction * bdesc->Push;
- if(dmg > 0)
- {
- float fX;
- float fY;
- if(dsqr == 0)
- {
- fX = dirX;
- fY = dirY;
- }
- else
- {
- float d = sqrt(dsqr);
- fX = dx/d;
- fY = dy/d;
- }
- msg.params[0] = 3;
- msg.fparams[1] = hitX;
- msg.fparams[2] = hitY;
- msg.fparams[3] = force * fX;
- msg.fparams[4] = force * fY;
- msg.params[5] = dmg;
- msg.params[6] = bdesc->Team;
- obj->Message(parent, M_GUNEXP, 1032, &msg);
- }
- }
- }
- }
- }
- }
- PXS : Library Code :
- require utils, pxparticles, pxbullet, wpsounds;
- CSprite* sentryBaseSprite;
- CSprite* sentryBodySprite;
- CSprite* sentryBarrelSprite;
- CSprite* sentryBarrelSprite2;
- CSprite* sentryMuzzleSprite;
- CSoundFile* sentryPlaceSound;
- CSoundFile* sentryRotateSound;
- CSoundFile* sentryRotateStartSound;
- CSoundFile* sentryRotateEndSound;
- CSoundFile* sentryShootSound;
- CSoundFile* sentryShootEndSound;
- CSoundFile* sentryAlertSound;
- PxBulletDesc* SentryBulletDesc;
- #WEAPON_KSENTRY
- CColMask* MASK_SENTRYGUN;
- void sentrygun::FirstFrame()
- {
- MASK_SENTRYGUN = new CColMask(6, 12, MakeRectMask(6, 12));
- CFile *f;
- f = GetAttachment("sentryplace.wav"); sentryPlaceSound = new CSoundFile(f);
- f = GetAttachment("sentryservoloop.wav"); sentryRotateSound = new CSoundFile(f);
- f = GetAttachment("sentryservostart.wav"); sentryRotateStartSound = new CSoundFile(f);
- f = GetAttachment("sentryservoend.wav"); sentryRotateEndSound = new CSoundFile(f);
- f = GetAttachment("sentryfireloop.wav"); sentryShootSound = new CSoundFile(f);
- f = GetAttachment("sentryfireend.wav"); sentryShootEndSound = new CSoundFile(f);
- f = GetAttachment("sentrybeeps2.wav"); sentryAlertSound = new CSoundFile(f);
- SentryBulletDesc = new PxBulletDesc;
- }
- // Loading resources
- void sentrygun::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("sentry_base.png"); sentryBaseSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("sentry_body.png"); sentryBodySprite = LoadSprite(f, 1, 0);
- f = GetAttachment("sentry_gun.png"); sentryBarrelSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("sentry_gun_firing.png"); sentryBarrelSprite2 = LoadSprite(f, 2, 0);
- f = GetAttachment("sentry_muzzle.png"); sentryMuzzleSprite = LoadSprite(f, 1, 0);
- }
- ///////////////////////////////////////////////////
- // PxSentryGun class
- PxSentryGun : CMine;
- PxSentryGun::PxSentryGun(CObject* Parent, CShootDesc* Desc)
- {
- // Maximum distance between a worm and the sentry for it to be detected
- SensorRadius = 360.0;
- //SensorLoseRadius = 500.0;
- // Gun parameters
- GunAmmunition = 20;
- GunDamage = 2;
- GunPush = 1;
- GunSpread = 0.05;
- GunFramesPerShot = 6;
- // Turret parameters
- TurretRotationSpeedIdle = 0.5;
- TurretRotationSpeedActive = 1.5;
- TurretIdleSweepAngle = 10.0;
- TurretOffsetX = 0;
- TurretOffsetY = -15;
- // Health parameters
- MaxHealth = 35;
- Health = MaxHealth;
- ExplosionDamage = 50;
- ExplosionBlast = 100;
- // Physics parameters
- //DumpingA = -1.0;
- //DumpingB = -1.0;
- //DumpingC = -1.0;
- BounceMultiplierX = 0.0;
- BounceMultiplierY = 1.0;
- // Number of frames to wait after activating before being able to fire
- DelayBeforeFiring = 60;
- // INTERNAL PARAMETERS
- TurretScale = 0.8;
- // Sprites
- SpriteBase = sentryBaseSprite->Index;
- SpriteBody = sentryBodySprite->Index;
- SpriteBarrel = sentryBarrelSprite->Index;
- SpriteBarrel2 = sentryBarrelSprite2->Index;
- SpriteMuzzle = sentryMuzzleSprite->Index;
- AnimSpeed = 0.2;
- // Private
- StunTurnsRemaining = 0;
- SensorRadiusSqr = 0.0;
- AnimCycle = 0.0;
- BaseOffsetX = 0;
- BaseOffsetY = 2;
- BarrelOffsetX = 17;
- BarrelOffsetY = 0;
- MuzzleOffsetX = 14;
- MuzzleOffsetY = 0;
- SweepDir = 1;
- Ammo = GunAmmunition;
- TurretActive = true;
- Target = NullObj;
- ShootTimer = 0;
- ActivateTimer = 0;
- SentryBeepTimer = 0;
- SentryBeepMinDelay = 60;
- Planted = false;
- Removed = false;
- Firing = false;
- LongRotation = false;
- LostTarget = false;
- LastTargetX = 0.0;
- LastTargetY = 0.0;
- // 180
- // |
- // 270 - + - 90
- // |
- // 0
- if(Desc->SpX < 0)
- {
- BaseSide = -1;
- }
- else
- {
- BaseSide = 1;
- }
- TurretSide = BaseSide;
- IdleTargetAngle = 180.0 - 90.0 * TurretSide;
- DisabledTargetAngle = IdleTargetAngle - 45.0 * TurretSide;
- TurretAngle = IdleTargetAngle;
- TargetAngle = IdleTargetAngle;
- RotationSpeed = TurretRotationSpeedIdle;
- NextRecalcZPlane = 0;
- ZPlane = 10.0;
- OwnerTeam = Desc->Team;
- CMineParams MParams;
- zero(&MParams);
- MParams.Prefuse = 0;
- MParams.Flags = 0;
- MParams.Bias = 0;
- MParams.Radius = 0;
- MParams.Fuse = 70;
- MParams.Damage = 48;
- MParams.BlastPower = 100;
- SetLayerOverride(LAYER_OILDRUM);
- SetMaskIndexOverride(3);
- super(Parent, &MParams, Desc, false, 0);
- ClType = EObjectClass(73);
- //Layer = LAYER_OILDRUM;
- //ColGroup = CMASK_DEFAULT_COLLIDEABLE;
- ShootSoundObj = CSound(NullObj);
- RotateSoundObj = CSound(NullObj);
- RotateStartSoundObj = CSound(NullObj);
- //ColMask = MASK_SENTRYGUN;
- }
- // Placeholder for CMagnetMissile
- void PxSentryGun::Collide(CGObject* Obj, int type)
- {
- if(Obj->ClType == OC_Landscape && Planted == false)
- {
- SpX = 0;
- SpY = 0;
- Planted = true;
- sentryPlaceSound->Play(1.0, 0.0, false);
- return;
- }
- SpX = SpX * BounceMultiplierX;
- SpY = SpY * BounceMultiplierY;
- super;
- }
- void PxSentryGun::Stun(int turns)
- {
- StunTurnsRemaining = turns;
- if(turns > 0) TurretActive = false;
- }
- // Applies blast damage
- // x, y : origin of the explosion
- // dmg : maximum damage the explosion should do
- void PxSentryGun::TakeExplosionDamage(fixed x, fixed y, int dmg)
- {
- if(dmg == 0) return;
- float fdmg = dmg;
- float dx = PosX - x;
- float dy = PosY - y;
- float distsqr = dx*dx + dy*dy;
- float fdmgsqr = fdmg*fdmg*4.0;
- fdmg = (1.0 - distsqr/fdmgsqr) * fdmg;
- dmg = fdmg;
- if(dmg > 0) TakeDamage(0, dmg);
- }
- // Applies direct damage (without any further calculation)
- // type should be always 0 (10 is for percentage-based damage and is reserved to the Battle Axe)
- void PxSentryGun::TakeDamage(int type, int dmg)
- {
- if(type == 10)
- {
- fixed fdmg = dmg;
- fdmg = Health * fdmg / 100.0;
- dmg = fdmg;
- }
- Health -= dmg;
- TurretActive = false;
- }
- void PxSentryGun::StartFiring()
- {
- if(Firing) return;
- Firing = true;
- ShootTimer = 0;
- ShootSoundObj = sentryShootSound->Play(1.0, 0.0, true);
- }
- void PxSentryGun::StopFiring()
- {
- if(Firing == false) return;
- Firing = false;
- if(ShootSoundObj != CSound(NullObj))
- {
- ShootSoundObj->Stop();
- ShootSoundObj = CSound(NullObj);
- }
- sentryShootEndSound->Play(1.0, 0.0, false);
- }
- void PxSentryGun::StartRotatingSound()
- {
- if(LongRotation) return;
- LongRotation = true;
- RotateStartSoundObj = sentryRotateStartSound->Play(0.95, 0.0, false);
- //RotateSoundObj = sentryRotateSound->Play(1.0, 0.0, true);
- }
- void PxSentryGun::StopRotatingSound()
- {
- if(LongRotation == false) return;
- LongRotation = false;
- if(RotateStartSoundObj != CSound(NullObj))
- {
- RotateStartSoundObj->Stop();
- RotateStartSoundObj = CSound(NullObj);
- }
- if(RotateSoundObj != CSound(NullObj))
- {
- RotateSoundObj->Stop();
- RotateSoundObj = CSound(NullObj);
- }
- sentryRotateEndSound->Play(0.95, 0.0, false);
- }
- // Called when the object is destroyed
- void PxSentryGun::Explode()
- {
- if(Removed) return;
- DoExplosion(PosX,PosY-20, ExplosionBlast, ExplosionDamage, 0, 0);
- SpeedDivider = 1000;
- SpX = 0.0;
- SpY = 0.0;
- GravityFactor = 0.0;
- IsMaterial = false;
- Stopped = 1;
- if(ShootSoundObj != CSound(NullObj))
- {
- ShootSoundObj->Stop();
- ShootSoundObj = CSound(NullObj);
- }
- if(RotateStartSoundObj != CSound(NullObj))
- {
- RotateStartSoundObj->Stop();
- RotateStartSoundObj = CSound(NullObj);
- }
- if(RotateSoundObj != CSound(NullObj))
- {
- RotateSoundObj->Stop();
- RotateSoundObj = CSound(NullObj);
- }
- }
- // Renders the object
- void PxSentryGun::Draw()
- {
- int baseX = PosX + BaseOffsetX;
- int baseY = PosY + BaseOffsetY;
- // Base
- if(BaseSide < 0)
- {
- AddSpriteEx(ZPlane+0.03, baseX, baseY, 262144 + SpriteBase, 0, 0, TurretScale);
- }
- else
- {
- AddSpriteEx(ZPlane+0.03, baseX, baseY, SpriteBase, 0, 0, TurretScale);
- }
- // Body
- float ang = (90 - TurretAngle) * 3.141593 / 180.0;
- float r;
- float g;
- float b;
- int TeamColor;
- if (OwnerTeam < 1)
- {
- TeamColor = 0;
- }
- else
- {
- TeamColor = GetTeamColor(OwnerTeam) + 1;
- }
- if (TeamColor == 1)
- {
- r = 0.65;
- g = 0.15;
- b = 0.15;
- }
- else if (TeamColor == 2)
- {
- r = 0.15;
- g = 0.15;
- b = 0.65;
- }
- else if (TeamColor == 3)
- {
- r = 0.15;
- g = 0.65;
- b = 0.15;
- }
- else if (TeamColor == 4)
- {
- r = 0.55;
- g = 0.55;
- b = 0.15;
- }
- else if (TeamColor == 5)
- {
- r = 0.55;
- g = 0.15;
- b = 0.55;
- }
- else if (TeamColor == 6)
- {
- r = 0.15;
- g = 0.55;
- b = 0.55;
- }
- else
- {
- r = 0.5;
- g = 0.5;
- b = 0.5;
- }
- if(Sinking)
- {
- r = r * (90.0 / 255.0);
- g = g * (90.0 / 255.0);
- b = b * (240.0 / 255.0);
- ClearColorMod();
- }
- SetColorMod(RGB(r * 255.0, g * 255.0, b * 255.0), 6);
- if(TurretSide < 0)
- AddSpriteEx(ZPlane, baseX+TurretScale*TurretOffsetX, baseY+TurretScale*TurretOffsetY, SpriteBody, 0, ang, TurretScale);
- else
- AddSpriteEx(ZPlane, baseX+TurretScale*TurretOffsetX, baseY+TurretScale*TurretOffsetY, 262144 + SpriteBody, 0, ang+3.141593, TurretScale);
- ClearColorMod();
- if(Sinking)
- {
- SetColorMod(RGB(90, 90, 240), 6);
- }
- // Barrels
- float realBarrelOffsetX = BarrelOffsetX;
- if(Firing)
- {
- realBarrelOffsetX = realBarrelOffsetX + 2.0 * sin(0.5 * GS->Tick);
- }
- float barrelX = baseX + TurretScale*(TurretOffsetX + cos(ang)*realBarrelOffsetX - sin(ang)*BarrelOffsetY);
- float barrelY = baseY + TurretScale*(TurretOffsetY + sin(ang)*realBarrelOffsetX - cos(ang)*BarrelOffsetY);
- if(Firing)
- {
- AddSpriteEx(ZPlane+0.02, barrelX, barrelY, SpriteBarrel2, AnimCycle, ang, TurretScale);
- if(AnimCycle < 0.5)
- {
- barrelX += TurretScale * (cos(ang)*MuzzleOffsetX - sin(ang)*MuzzleOffsetY);
- barrelY += TurretScale * (sin(ang)*MuzzleOffsetX - cos(ang)*MuzzleOffsetY);
- //AddSpriteEx(ZPlane+0.01, barrelX, barrelY, SpriteMuzzle, 0, ang, 1);
- CQuad q;
- FillSpriteQuad(&q, SpriteMuzzle, 0, 0);
- TransformQuad(&q, ang, TurretScale, TurretScale, barrelX, barrelY);
- q.blend = 1;
- for(int i=0 ; i<4 ; i+=1) q.v[i].color = RGB(255,255,255);
- AddSpriteQ(ZPlane+0.01, &q, SpriteMuzzle, 0, 64);
- }
- }
- else
- {
- AddSpriteEx(ZPlane+0.02, barrelX, barrelY, SpriteBarrel, 0, ang, TurretScale);
- }
- }
- bool PxSentryGun::IsTargetVisible(CGObject *target)
- {
- int hitX;
- int hitY;
- if(TraceLine(this, PosX + BaseOffsetX + TurretScale*TurretOffsetX, PosY + BaseOffsetY + TurretScale*TurretOffsetY,
- target->PosX, target->PosY, 2, &hitX, &hitY) == NullObj)
- return true;
- else
- return false;
- }
- void PxSentryGun::TurretThink()
- {
- int turretX = PosX + BaseOffsetX + TurretScale*TurretOffsetX;
- int turretY = PosY + BaseOffsetY + TurretScale*TurretOffsetY;
- int hitX;
- int hitY;
- if(TurretActive)
- {
- // Looking for targets
- if(Target == NullObj)
- {
- if(SensorRadiusSqr == 0.0)
- SensorRadiusSqr = SensorRadius * SensorRadius;
- float best_distance;
- for(int i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = CGObject(Env->Objs.Objs[i]);
- if(obj == NullObj) continue;
- // if it's a worm...
- if(obj->ClType == OC_Worm)
- {
- CWorm *worm = CWorm(obj);
- // if it's not friendly...
- if(OwnerTeam < 1 || GetTeamColor(worm->WormTeam) != GetTeamColor(OwnerTeam))
- {
- // if it's moving...
- if(obj->ObjState == WS_WALKING || obj->SpX != 0 || obj->SpY != 0)
- {
- float dx = obj->PosX - turretX;
- float dy = obj->PosY - turretY;
- float d = dx*dx + dy*dy;
- // if it's inside the sentry's detection radius...
- if(d <= SensorRadiusSqr)
- {
- // if it's visible...
- if(IsTargetVisible(obj))
- {
- // -> potential target
- if(Target == NullObj || d < best_distance)
- {
- // in the end, only the closest potential target will be selected
- Target = obj;
- best_distance = d;
- }
- }
- }
- }
- }
- }
- }
- if(Target != NullObj)
- {
- // Got a target, make a beeping sound
- //PlayLocalSound(88, 5, 2.0, 1.0, &Snd);
- if(SentryBeepTimer <= 0)
- {
- sentryAlertSound->Play(1.0, 0.0, false);
- SentryBeepTimer = SentryBeepMinDelay;
- }
- ActivateTimer = DelayBeforeFiring;
- }
- }
- if(Target == NullObj)
- {
- // Idle
- TargetAngle = IdleTargetAngle + SweepDir * TurretIdleSweepAngle;
- LostTarget = false;
- RotationSpeed = TurretRotationSpeedIdle;
- }
- else
- {
- // Tracking (TODO)
- if(IsTargetVisible(Target))
- {
- LostTarget = false;
- TargetAngle = (atan2(Target->PosX - turretX, Target->PosY - turretY) * 180.0) / 3.141593;
- }
- else
- {
- if(LostTarget == false)
- {
- LastTargetX = Target->PosX;
- LastTargetY = Target->PosY;
- StopFiring();
- }
- LostTarget = true;
- TargetAngle = (atan2(LastTargetX - turretX, LastTargetY - turretY) * 180.0) / 3.141593;
- }
- if(TargetAngle < 0.0) TargetAngle += 360.0;
- if(TargetAngle > 360.0) TargetAngle -= 360.0;
- RotationSpeed = TurretRotationSpeedActive;
- }
- }
- else
- {
- // Disabled
- TargetAngle = DisabledTargetAngle;
- Target = NullObj;
- StopFiring();
- RotationSpeed = TurretRotationSpeedIdle;
- }
- // Rotate the turret towards the target angle
- float speed = TargetAngle - TurretAngle;
- if(RotateStartSoundObj != CSound(NullObj) && RotateStartSoundObj->isAlive() == false)
- {
- RotateStartSoundObj->Stop();
- RotateStartSoundObj = CSound(NullObj);
- RotateSoundObj = sentryRotateSound->Play(0.95, 0.0, true);
- }
- if(TurretActive && Target != NullObj)
- {
- if(speed >= 2*RotationSpeed || speed <= -2*RotationSpeed)
- {
- StartRotatingSound();
- }
- else
- {
- StopRotatingSound();
- }
- }
- else
- {
- StopRotatingSound();
- }
- if(ActivateTimer > 0) ActivateTimer = ActivateTimer - 1;
- if(SentryBeepTimer > 0) SentryBeepTimer = SentryBeepTimer - 1;
- if(speed >= RotationSpeed)
- {
- TurretAngle += RotationSpeed;
- StopFiring();
- }
- else if(speed <= -RotationSpeed)
- {
- TurretAngle -= RotationSpeed;
- StopFiring();
- }
- else
- {
- TurretAngle = TargetAngle;
- if(TurretActive)
- {
- if(Target == NullObj)
- {
- // If the target angle has been reached while the turret is idle, reverse the sweep direction
- // so it looks like the sentry is scanning the area
- SweepDir = -SweepDir;
- }
- else
- {
- if(LostTarget)
- {
- Target = NullObj;
- }
- else
- {
- if(ActivateTimer <= 0) StartFiring();
- }
- // Got focus on the target, is it visible?
- //if(IsTargetVisible(obj))
- //{
- //StartFiring();
- //}
- //else
- //{
- // StopFiring();
- //}
- }
- }
- }
- // Turret rotated over itself, change the sentry's idle target angle so the turret faces the other way when it goes back to idle
- if((180 - TurretAngle) * TurretSide < 0)
- {
- TurretSide = -TurretSide;
- IdleTargetAngle = 180.0 - 90.0 * TurretSide;
- DisabledTargetAngle = IdleTargetAngle - 45.0 * TurretSide;
- }
- // Firing
- if(Firing)
- {
- AnimCycle = AnimCycle + AnimSpeed;
- if(AnimCycle >= 1.0) AnimCycle -= 1.0;
- if(ShootTimer <= 0)
- {
- float ang = (90 - TurretAngle) * 3.141593 / 180.0;
- CShootDesc SDesc;
- zero(&SDesc);
- SDesc.Team = 0;
- SDesc.X = turretX;
- SDesc.Y = turretY;
- SDesc.SpX = cos(ang);
- SDesc.SpY = sin(ang);
- SentryBulletDesc->Damage = GunDamage;
- SentryBulletDesc->Push = GunPush;
- SentryBulletDesc->Count = 1;
- if(RandomInt(1, 5) == 1)
- SentryBulletDesc->Spread = 0.0; // 20% probability to fire a bullet at pin-point accuracy
- else
- SentryBulletDesc->Spread = GunSpread;
- FireBullets(this, &SDesc, SentryBulletDesc);
- // Shell ejection
- PxParticle *p = new PxParticle(115, turretX, turretY);
- p->SetAnimSpeed(0.1);
- p->SetLifeTime(100);
- float eject_ang = ang - TurretSide * 1.570797 + RandomFloat(-0.3, 0.3);
- float eject_vel = RandomFloat(2.0, 3.0);
- p->SetVelocity(eject_vel * cos(eject_ang), eject_vel * sin(eject_ang));
- p->SetAirResistance(0.0);
- p->GravityFactor(1.0);
- p->SetAlpha(255);
- p->SetSize(1.0, 1.0);
- //PlayLocalSound(78, 5, 1.0, 1.0, &Snd);
- ShootTimer = GunFramesPerShot;
- Ammo = Ammo - 1;
- if(Ammo <= 0)
- {
- StopFiring();
- TurretActive = false;
- }
- }
- ShootTimer = ShootTimer - 1;
- }
- }
- // Called when a new turn begins
- void PxSentryGun::OnTurnBegin(int Team)
- {
- // Reload the turret and activate it
- Target = NullObj;
- if(StunTurnsRemaining > 0)
- {
- if(Team == OwnerTeam) StunTurnsRemaining = StunTurnsRemaining - 1;
- }
- else
- {
- TurretActive = true;
- Ammo = GunAmmunition;
- }
- }
- void PxSentryGun::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- // Drawing operations are done here
- if(Type == M_DRAWQUEUE)
- {
- if(Removed) return;
- if(Sinking) SetColorMod(RGB(90, 90, 240), 6);
- Draw();
- if(Sinking) ClearColorMod();
- // Recalculate Z plane periodically to make sure magnets are drawn properly when overlapping each other
- if(NextRecalcZPlane <= 0)
- {
- local matches = 0;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj == this) continue;
- if(obj is PxSentryGun)
- {
- local sentry = PxSentryGun(obj);
- float dX = sentry->PosX - PosX;
- float dY = sentry->PosY - PosY;
- float r2 = dX*dX + dY*dY;
- if(r2 < 900.0)
- {
- if(sentry->ZPlane == ZPlane)
- {
- sentry->ZPlane = sentry->ZPlane + 0.1;
- }
- matches = matches + 1;
- }
- }
- }
- if(matches == 0) ZPlane = 10;
- NextRecalcZPlane = 200;
- }
- else
- {
- NextRecalcZPlane = NextRecalcZPlane - 1;
- }
- return;
- }
- // Damage handling
- if(Removed==false)
- {
- if(Type == M_EXPLOSION)
- {
- TakeExplosionDamage(MData->fparams[1], MData->fparams[2], MData->params[4]);
- }
- else if(Type == M_GUNEXP)
- {
- TakeDamage(MData->params[0], MData->params[5]);
- }
- }
- super;
- // This is done every frame (derp)
- if(Type == M_FRAME)
- {
- if(Removed)
- {
- Free(true);
- return;
- }
- else
- {
- if(Sinking)
- {
- TurretActive = false;
- }
- TurretThink();
- if(Health <= 0)
- {
- Explode();
- Removed = true;
- }
- }
- }
- }
- ///////////////////////////////////////////////////
- // CTurnGame overrides
- override void CTurnGame::SetCurrentTeam(int Team)
- {
- super;
- for(local i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = Env->Objs.Objs[i];
- if(obj == NullObj) continue;
- if(obj is PxSentryGun)
- {
- PxSentryGun *sentry = PxSentryGun(obj);
- sentry->OnTurnBegin(Team);
- }
- }
- }
- ///////////////////////////////////////////////////
- // CWorm overrides
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Sentry Gun"))
- {
- local ang = (1 - FireAngle) * 3.14159;
- if (TurnSide < 0)
- {
- ang = 6.28318 - ang;
- }
- CShootDesc SDesc;
- zero(&SDesc);
- local BaseForce = 0.3;
- SDesc.Team = WormTeam;
- SDesc.X = PosX;
- SDesc.Y = PosY;
- SDesc.SpX = SpX * 0.5 + TurnSide * BaseForce;
- SDesc.SpY = SpY * 0.5 - 0.15;
- new PxSentryGun(GetObject(25, 0), &SDesc);
- }
- else
- {
- super;
- }
- }
- PXS : Library Code :
- require utils, pxparticles, pxtexbeam, wpsounds;
- //////////////////////////
- // Global variables
- float TazerSegmentLength;
- int TazerNumSegments;
- int TazerLifeTime;
- int TazerLifeTimeAfterHit;
- int TazerStartDie;
- float TazerSearchRadius;
- float TazerSearchRadiusSqr;
- float TazerNoiseScale;
- int TazerWormDamage;
- int TazerObjectDamage;
- bool TazerCanFire;
- // Most of those variables should be members of CTazerShot, but since PX has so many memory leaks, better have static tables
- // Since there will be only one worm using a tazer at once, that shouldn't be a problem
- int TazerNumPoints;
- int TazerQueueHead;
- int TazerQueueTail;
- float TazerPointsX[128];
- float TazerPointsY[128];
- float TazerNoise[128];
- CGObject* TazerIgnoreList[64];
- int TazerIgnoreNum;
- CTraceRes *TazerTrace;
- CSprite* laserSprite;
- CSprite* tazer_lightningBeamSprite;
- CSprite* tazer_lightningGlowSprite;
- CSprite* wormTazedSprite1;
- CSprite* wormTazedSprite2;
- CSoundFile* tazerLoopSound;
- CSoundFile* tazerHitSound;
- #WEAPON_TAZER
- //CLogFile *tazerLog;
- ///////////////////////////////////////////////////
- // Initialization
- void tazer::FirstFrame()
- {
- CFile *f;
- f = GetAttachment("sentryservoloop.wav"); tazerLoopSound = new CSoundFile(f);
- f = GetAttachment("sentryservoloop.wav"); tazerHitSound = new CSoundFile(f);
- TazerSegmentLength = 10.0; // The length of each segment of the arc
- TazerNumSegments = 33; // Maximum number of segments in the arc, must be a power of 2 plus 1
- TazerLifeTime = 16; // How far the arc can progress
- TazerLifeTimeAfterHit = 20; // Same, but after the initial hit (for making chains slightly easier)
- TazerStartDie = 6; // The arc starts to fade out when its life reaches this value
- TazerNoiseScale = 10.0;
- TazerWormDamage = 24;
- TazerObjectDamage = 12;
- TazerSearchRadius = TazerSegmentLength * TazerLifeTimeAfterHit;
- TazerSearchRadiusSqr = TazerSearchRadius * TazerSearchRadius;
- TazerNumPoints = 0;
- TazerTrace = new CTraceRes;
- TazerObjectsZappedNum = 0;
- TazerCanFire = true;
- //tazerLog = new CLogFile("tazer_log.txt");
- }
- void tazer::InitGraphic()
- {
- CFile *f;
- f = GetAttachment("worm_tazed1.png"); wormTazedSprite1 = LoadSprite(f, 4, 0);
- f = GetAttachment("worm_tazed2.png"); wormTazedSprite2 = LoadSprite(f, 4, 0);
- f = GetAttachment("lightning_beam.png"); tazer_lightningBeamSprite = LoadSprite(f, 1, 0);
- f = GetAttachment("lightning_glow.png"); tazer_lightningGlowSprite = LoadSprite(f, 1, 0);
- }
- ///////////////////////////////////////////////////
- // CTazerDamage
- CTazerDamage : CObject;
- CTazerDamage::CTazerDamage(CObject *parent, CGObject *target, int side)
- {
- super(parent, GS);
- Target = target;
- DamageSide = side;
- if(Target->ClType == OC_Worm)
- {
- CWorm *w = CWorm(Target);
- w->Taze();
- }
- NextDie = 24;
- GlowSize = 10.0;
- Removed = false;
- Dead = false;
- PosX = target->PosX;
- PosY = target->PosY;
- PRegister(&Target);
- tazerHitSound->Play(1.0, 0.0, false);
- }
- void CTazerDamage::Zap(CGObject* obj)
- {
- if(obj->ClType == OC_Mine)
- {
- // Trigger mines
- CMine *mine = CMine(obj);
- // If the mine is not a special mine, can be triggered, and has not been triggered yet
- if(mine->Radius > 0 && mine->Active == 0 && mine->Prefuse <= 0)
- {
- // Almost instant explosion
- mine->Fuse = 400;
- // Trigger the mine
- mine->Active = 1;
- mine->nPulses = 2;
- }
- }
- else
- {
- CMessageData msg;
- msg.params[0] = 0;
- msg.fparams[1] = obj->PosX;
- msg.fparams[2] = obj->PosY;
- msg.fparams[3] = 1.2 * DamageSide;
- msg.fparams[4] = -4.0;
- if(obj->ClType == OC_Worm)
- {
- CWorm *w = CWorm(Target);
- w->UnTaze();
- msg.params[5] = TazerWormDamage;
- }
- else
- {
- msg.params[5] = TazerObjectDamage;
- }
- msg.params[6] = 0;
- if(#WEAPON_MAGNET)
- {
- if(obj is CMagnet)
- {
- // Instantly destroy magnets
- CMagnet *mag = CMagnet(obj);
- mag->Health = 1;
- mag->Message(this, M_GUNEXP, 1032, &msg);
- return;
- }
- }
- if(#WEAPON_FAN)
- {
- if(obj is PxFan)
- {
- // Instantly destroy fans
- local fanobj = PxFan(obj);
- fanobj->Health = 1;
- fanobj->TakeDamage(TazerObjectDamage, 0);
- fanobj->Message(this, M_GUNEXP, 1032, &msg);
- return;
- }
- }
- if(#WEAPON_BOWLINGBALL)
- {
- if(obj is CBowlingBall)
- {
- // Send bowling balls flying
- CBowlingBall *ball = CBowlingBall(obj);
- ball->Zap(1);
- return;
- }
- }
- if(#WEAPON_KSENTRY)
- {
- if(obj is PxSentryGun)
- {
- // Stun sentries
- PxSentryGun *sentry = PxSentryGun(obj);
- sentry->Stun(2);
- sentry->Message(this, M_GUNEXP, 1032, &msg);
- return;
- }
- }
- obj->Message(this, M_GUNEXP, 1032, &msg);
- }
- }
- void CTazerDamage::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if(Removed) return;
- if((NextDie <= 0) || (Target == CGObject(NullObj)))
- {
- if(Target != CGObject(NullObj))
- {
- Zap(Target);
- }
- PUnregister(&Target);
- Removed = true;
- Free(true);
- return;
- }
- NextDie = NextDie - 1;
- GlowSize = RandomFloat(0.4, 0.7);
- PosX = Target->PosX;
- PosY = Target->PosY;
- PxParticle *p = new PxParticle(tazer_lightningGlowSprite->Index, PosX, PosY);
- p->SetBlendMode(1);
- p->SetLifeTime(50);
- p->SetRandomVelocity(1.0, 3.0);
- p->SetAirResistance(0.0);
- p->GravityFactor(1.0);
- p->SetAlpha(255);
- p->SetColor(255,200,0);
- p->SetStartSize(0.1, 0.1);
- p->SetEndSize(0.01, 0.01);
- }
- if(Type == M_DRAWQUEUE)
- {
- if(Removed) return;
- CQuad q;
- FillSpriteQuad(&q, tazer_lightningGlowSprite->Index, 0, 0);
- TransformQuad(&q, 0, GlowSize, GlowSize, PosX, PosY);
- q.blend = 1;
- for(i=0 ; i<4 ; i+=1) q.v[i].color = RGB(80,100,255);
- AddSpriteQ(9.9, &q, tazer_lightningGlowSprite->Index, 0, 64);
- }
- super;
- }
- ///////////////////////////////////////////////////
- // CTazerShot
- CTazerShot : CObject;
- CTazerShot::CTazerShot(CObject *parent, CWorm *owner)
- {
- super(parent, GS);
- ClType = OC_AirStrike;
- ClearIgnoreList();
- AddToIgnoreList(owner);
- float ang = (1 - owner->FireAngle) * 3.14159;
- if(owner->TurnSide < 0)
- {
- ang = 6.28318 - ang;
- }
- LifeTime = TazerLifeTime;
- Removed = false;
- Dead = false;
- DieFraction = 0.0;
- DieRate = 0.05;
- DirX = sin(ang);
- DirY = -cos(ang);
- PosX = owner->PosX + 4 * DirX;
- PosY = owner->PosY + 4 * DirY;
- LastX = owner->PosX;
- LastY = owner->PosY;
- NextProgress = 0;
- StopProgress = false;
- NumRemoveOnNextLink = 0;
- ClearPoints();
- AddPoint(PosX, PosY);
- SoundObj = tazerLoopSound->Play(1.0, 0.0, false);
- }
- void CTazerShot::ClearPoints()
- {
- TazerNumPoints = 0;
- TazerQueueHead = 0;
- TazerQueueTail = 0;
- }
- float CTazerShot::PointX(int i)
- {
- i = (TazerQueueHead+i) % 64;
- return TazerPointsX[i];
- }
- float CTazerShot::PointY(int i)
- {
- i = (TazerQueueHead+i) % 64;
- return TazerPointsY[i];
- }
- void CTazerShot::AddPoint(float x, float y)
- {
- TazerPointsX[TazerQueueTail] = x;
- TazerPointsY[TazerQueueTail] = y;
- TazerQueueTail = (TazerQueueTail+1) % 64;
- TazerNumPoints += 1;
- }
- void CTazerShot::RemovePoint()
- {
- TazerQueueHead = (TazerQueueHead+1) % 64;
- TazerNumPoints -= 1;
- }
- void CTazerShot::ClearIgnoreList()
- {
- TazerIgnoreNum = 0;
- }
- bool CTazerShot::AddToIgnoreList(CGObject *obj)
- {
- if(TazerIgnoreNum == 63) return false;
- TazerIgnoreList[TazerIgnoreNum] = obj;
- TazerIgnoreNum += 1;
- return true;
- }
- bool CTazerShot::IsValidTarget(CGObject *obj)
- {
- bool ok = false;
- ///////////////////////////////
- if(obj->ClType == OC_Worm) ok = true;
- if(obj->ClType == OC_Mine) ok = true;
- if(obj->ClType == OC_OilDrum) ok = true;
- if(obj->ClType == OC_Crate) ok = true;
- if(#WEAPON_MAGNET)
- {
- if(obj is CMagnet) ok = true;
- }
- if(#WEAPON_BOWLINGBALL)
- {
- if(obj is CBowlingBall) ok = true;
- }
- if(#WEAPON_FAN)
- {
- if(obj is PxFan) ok = true;
- }
- if(obj is PxSentryGun) ok = true;
- ///////////////////////////////
- if(ok)
- {
- for(int i=0 ; i<TazerIgnoreNum ; i += 1)
- {
- if(TazerIgnoreList[i] == obj) return false;
- }
- return true;
- }
- return false;
- }
- CGObject *CTazerShot::FindTarget()
- {
- float best_distance;
- CGObject *target = NullObj;
- for(int i = 1; i < Env->Objs.Count; i+=1)
- {
- local obj = CGObject(Env->Objs.Objs[i]);
- if(obj == NullObj) continue;
- if(IsValidTarget(obj))
- {
- float dx = obj->PosX - PosX;
- float dy = obj->PosY - PosY;
- float d = dx*dx + dy*dy;
- if(d <= TazerSearchRadiusSqr)
- {
- if(target == NullObj || d < best_distance)
- {
- target = obj;
- best_distance = d;
- }
- }
- }
- }
- return target;
- }
- void CTazerShot::GenerateNoise(float scale, float start, float end)
- {
- int i;
- int k = TazerNumSegments;
- int l = k >> 1;
- for(i=0 ; i<TazerNumSegments ; i+=1) TazerNoise[i] = 0.0;
- TazerNoise[0] = start;
- TazerNoise[TazerNumSegments-1] = end;
- while(l > 0)
- {
- for(i=l ; i<TazerNumSegments ; i+=k)
- {
- TazerNoise[i] = (TazerNoise[i-l] + TazerNoise[i+l]) * 0.5 + RandomFloat(-scale, scale);
- }
- k = l;
- l = k >> 1;
- }
- }
- void CTazerShot::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if(Removed) return;
- GenerateNoise(1.0, 0.0, 0.0);
- if(NextProgress == 0)
- {
- //NextProgress = RandomInt(0,2);
- NextProgress = 0; // don't slow the progress down, maybe it looks better that way?
- }
- else
- {
- NextProgress = NextProgress - 1;
- return;
- }
- if(TazerNumPoints >= TazerNumSegments || NumRemoveOnNextLink > 0)
- {
- RemovePoint();
- NumRemoveOnNextLink = NumRemoveOnNextLink - 1;
- }
- if(LifeTime == 0)
- {
- if(SoundObj != CSound(NullObj))
- {
- SoundObj->Stop();
- SoundObj = CSound(NullObj);
- }
- Removed = true;
- Free(true);
- return;
- }
- else
- LifeTime = LifeTime - 1;
- bool snapToTarget = false;
- CGObject *target = NullObj;
- if(LifeTime <= TazerStartDie)
- {
- // The electrical arc is dying, fade it out
- RemovePoint();
- RemovePoint();
- NumRemoveOnNextLink = NumRemoveOnNextLink - 2;
- float f = TazerStartDie;
- f = LifeTime / f;
- DieFraction = 1.0 - f;
- }
- else
- DieFraction = 0.0;
- if(StopProgress) return;
- target = FindTarget();
- if(target != NullObj)
- {
- // Curve towards targets
- float tx = target->PosX - PosX;
- float ty = target->PosY - PosY;
- float td = sqrt(tx*tx + ty*ty);
- tx = tx/td;
- ty = ty/td;
- float l = sqrt(TazerSegmentLength / td);
- // Near enough?
- if(l >= 0.9)
- {
- // Snap to the target
- l = 1.0;
- snapToTarget = true;
- // Add the target to the ignore list so we don't zap it again and again
- AddToIgnoreList(target);
- CGObject *newtarget = FindTarget();
- if(newtarget != CGObject(NullObj))
- {
- // Reset the life time of the electrical arc
- LifeTime = TazerLifeTimeAfterHit;
- }
- else
- StopProgress = true;
- // Make it pause a bit
- //NextProgress = RandomInt(2,4);
- NextProgress = 14; // longer pause
- // The number of points to remove from the arc the next time it links with something
- // Kinda hard to explain but it's basically for removing excess points from the arc to make it look like
- // it's linking the currently hit objects with the previously hit one.
- NumRemoveOnNextLink = TazerNumPoints;
- // Bam, damage
- if(tx < 0)
- new CTazerDamage(GetObject(25, 0), target, -1);
- else
- new CTazerDamage(GetObject(25, 0), target, 1);
- }
- DirX = DirX + (tx - DirX) * l;
- DirY = DirY + (ty - DirY) * l;
- td = sqrt(DirX*DirX + DirY*DirY);
- DirX = DirX/td;
- DirY = DirY/td;
- }
- else
- {
- // No target, take a random direction
- DirX = DirX + RandomFloat(-1.0, 1.0);
- DirY = DirY + RandomFloat(-1.0, 1.0);
- float td = sqrt(DirX*DirX + DirY*DirY);
- if(td == 0)
- {
- DirX = 0;
- DirY = 1;
- }
- else
- {
- DirX = DirX/td;
- DirY = DirY/td;
- }
- }
- if(snapToTarget == false)
- {
- // Avoid terrain
- float endx = PosX + DirX * TazerSegmentLength * 2;
- float endy = PosY + DirY * TazerSegmentLength * 2;
- TraceLineEx(this, PosX, PosY, endx, endy, CMASK_TERRAIN, TazerTrace);
- if(TazerTrace->StartsSolid)
- {
- TraceLineEx(this, LastX, LastY, endx, endy, CMASK_TERRAIN, TazerTrace);
- if(TazerTrace->StartsSolid)
- {
- Dead = true;
- return;
- }
- }
- if(TazerTrace->Hit)
- {
- if(true)
- {
- // So we just hit some terrain, what are we supposed to do now?
- // Temporary vars, we'll use them for calculations later
- float tx;
- float ty;
- float dx;
- float dy;
- float newPosX;
- float newPosY;
- // Move away from the terrain to make sure we aren't too close to it
- newPosX = TazerTrace->HitX + TazerTrace->NormalX * TazerSegmentLength;
- newPosY = TazerTrace->HitY + TazerTrace->NormalY * TazerSegmentLength;
- // Let's try to follow the shape of the terrain and see if we're getting anywhere
- dx = TazerTrace->TangentX;
- dy = TazerTrace->TangentY;
- // New direction doesn't matter if we don't have a target, heh
- if(target != NullObj)
- {
- // Now we can either follow the terrain in one direction or the other
- // See which direction brings us closer to the target
- // Case 1: Projected new position if we follow the tangent's direction
- float x1 = newPosX + dx * 2 * TazerSegmentLength;
- float y1 = newPosY + dy * 2 * TazerSegmentLength;
- // Case 2: Projected new position if we follow the opposite direction
- float x2 = newPosX - dx * 2 * TazerSegmentLength;
- float y2 = newPosY - dy * 2 * TazerSegmentLength;
- // Distance to target when using case 1
- tx = target->PosX - x1;
- ty = target->PosY - y1;
- float d1 = tx*tx+ty*ty;
- // Distance to target when using case 2
- tx = target->PosX - x2;
- ty = target->PosY - y2;
- float d2 = tx*tx+ty*ty;
- if(d2 < d1)
- {
- // Case 2 brings us closer to the target, use the opposite tangent then
- dx = -dx;
- dy = -dy;
- x1 = x2;
- y1 = y2;
- }
- }
- // Calculate the final movement direction vector
- newPosX += dx * TazerSegmentLength;
- newPosY += dy * TazerSegmentLength;
- DirX = newPosX - PosX;
- DirY = newPosY - PosY;
- float td = sqrt(DirX*DirX + DirY*DirY);
- DirX = DirX / td;
- DirY = DirY / td;
- }
- else
- {
- // OLD ALGORITHM
- float tx = TazerTrace->HitX - PosX;
- float ty = TazerTrace->HitY - PosY;
- float l = 1 - (sqrt(tx*tx+ty*ty) / (TazerSegmentLength * 2));
- tx = TazerTrace->HitX + TazerTrace->NormalX * TazerSegmentLength;
- ty = TazerTrace->HitY + TazerTrace->NormalY * TazerSegmentLength;
- DirX = tx - PosX;
- DirY = ty - PosY;
- float td = sqrt(DirX*DirX + DirY*DirY);
- DirX = DirX/td;
- DirY = DirY/td;
- if(target != NullObj)
- {
- float x1 = PosX + DirX * TazerSegmentLength;
- float y1 = PosY + DirY * TazerSegmentLength;
- float x2 = PosX - DirX * TazerSegmentLength;
- float y2 = PosY - DirY * TazerSegmentLength;
- tx = target->PosX - x1;
- ty = target->PosY - y1;
- float d1 = tx*tx+ty*ty;
- tx = target->PosX - x2;
- ty = target->PosY - y2;
- float d2 = tx*tx+ty*ty;
- if(d2 < d1)
- {
- DirX = -DirX;
- DirY = -DirY;
- x1 = x2;
- y1 = y2;
- }
- int hitx;
- int hity;
- if(TraceLine(this, PosX, PosY, x1, y1, CMASK_TERRAIN, &hitx, &hity) != NullObj)
- {
- DirX = -DirX;
- DirY = -DirY;
- }
- }
- }
- }
- }
- LastX = PosX;
- LastY = PosY;
- if(snapToTarget)
- {
- PosX = target->PosX;
- PosY = target->PosY;
- }
- else
- {
- PosX += DirX * TazerSegmentLength;
- PosY += DirY * TazerSegmentLength;
- }
- AddPoint(PosX, PosY);
- }
- if(Type == M_DRAWQUEUE)
- {
- if(Removed) return;
- if(TazerNumPoints >= 2)
- {
- StartTexturedBeam(this, 10, tazer_lightningBeamSprite->Index, 0.0, 1);
- CQuad q;
- int num = (TazerNumPoints - 1);
- for(int i=0 ; i<=num ; i += 1)
- {
- float t = num;
- t = i / t;
- float x = PointX(i);
- float y = PointY(i);
- if(i > 0 && i < num)
- {
- float dx = y - PointY(i-1);
- float dy = PointX(i-1) - x;
- float d = sqrt(dx*dx+dy*dy);
- dx = dx / d;
- dy = dy / d;
- x = x + TazerNoiseScale * TazerNoise[i-1] * dx;
- y = y + TazerNoiseScale * TazerNoise[i-1] * dy;
- }
- // Dome curve thing where f(0)=f(1)=0 and f(0.5)=1
- // basically that means that the beam will be thicker in the middle and thinner at the extremities
- float f = (4.0 * t * (1.0-t) + 0.1);
- if(f > 1.0) f = 1.0;
- float f2 = f * (1.0 - DieFraction);
- float s;
- float r;
- float g;
- float b;
- r = 80.0 * f2;
- g = 100.0 * f2;
- b = 255.0 * f2;
- TexturedBeamPoint(x, y, f * 9.0, t, RGB(r,g,b));
- FillSpriteQuad(&q, tazer_lightningGlowSprite->Index, 0, 0);
- if(i==num-1)
- {
- // Make the tip of the arc glow stronger
- TransformQuad(&q, 0, 0.9, 0.9, x, y);
- }
- else
- {
- TransformQuad(&q, 0, 0.3, 0.3, x, y);
- }
- q.blend = 1;
- for(int k=0 ; k<4 ; k+=1) q.v[k].color = RGB(r,g,b);
- AddSpriteQ(9.9, &q, tazer_lightningGlowSprite->Index, 0, 64);
- }
- EndTexturedBeam();
- }
- }
- super;
- }
- override void CTurnGame::SetCurrentTeam(int Team)
- {
- super;
- TazerCanFire = true;
- }
- ///////////////////////////
- // CWorm overrides
- override CWorm::CWorm(CObject* Parent, int aTeam, int aIndex, CWormParams* params)
- {
- super;
- Tazed = false;
- TazedPosX = PosX;
- TazedPosY = PosY;
- TazedAnim = 0;
- TazedAnimCycle = 0.0;
- TazedAnimAngle = float(0.0);
- }
- void CWorm::Taze()
- {
- Tazed = true;
- TazedPosX = PosX;
- TazedPosY = PosY;
- if(RandomInt(0,1) == 0)
- {
- TazedAnim = wormTazedSprite1->Index;
- }
- else
- {
- TazedAnim = wormTazedSprite2->Index;
- }
- TazedAnimCycle = 0.0;
- TazedAnimAngle = 3.141593 + RandomFloat(-0.2, 0.2);
- //TazedAnimAngle = 0.0;
- SetState(WS_IDLE);
- SpeedDivider = 1000;
- }
- void CWorm::UnTaze()
- {
- Tazed = false;
- SpeedDivider = 1;
- }
- override void CWorm::Message(CObject* sender, EMType Type, int MSize, CMessageData* MData)
- {
- if(Type == M_FRAME)
- {
- if(Tazed)
- {
- // Makes the worm invisible
- Anim->Reset();
- Anim->SetAnimEx(136, 0.0);
- TazedAnimCycle = TazedAnimCycle + 0.1;
- if(TazedAnimCycle >= 1.0) TazedAnimCycle -= 1.0;
- if(int(TazedPosX) != int(PosX) || int(TazedPosY) != int(PosY))
- {
- UnTaze();
- }
- }
- }
- if(Type == M_DRAWQUEUE)
- {
- if(Tazed)
- {
- if(TurnSide < 0)
- {
- AddSpriteEx(8, PosX, PosY, TazedAnim + 262144, TazedAnimCycle, TazedAnimAngle, 1.0);
- }
- else
- {
- AddSpriteEx(8, PosX, PosY, TazedAnim, TazedAnimCycle, TazedAnimAngle, 1.0);
- }
- }
- }
- super;
- }
- override void CWorm::FireFinal(CWeapon* Weap, CShootDesc* Desc)
- {
- if(Weap->CheckName("Tazer"))
- {
- if(TazerCanFire)
- {
- new CTazerShot(GetObject(25, 0), this);
- TazerCanFire = false;
- }
- }
- else
- {
- super;
- }
- }
- PXS : Compiling..
- PXS : Compiled
- PXS : N Classes : 30
- PXS : processing script class MissileIndex
- PXS : instance size : 4
- PXS : processing script class RandomsGens
- PXS : processing script class WormsRelated
- PXS : processing script class Maths
- PXS : processing script class sync_script
- PXS : instance size : 4
- PXS : processing script class tracers
- PXS : instance size : 4
- PXS : processing script class all_utils
- PXS : processing script class px_enums
- PXS : instance size : 4
- PXS : processing script class layer_override
- PXS : instance size : 4
- PXS : processing script class ldetector_script
- PXS : instance size : 4
- PXS : processing script class antiglitch_s
- PXS : instance size : 4
- PXS : processing script class darkness_script
- PXS : instance size : 4
- PXS : processing script class friendlymines
- PXS : processing script class nades
- PXS : processing script class turretbase
- PXS : instance size : 4
- PXS : processing script class mineturret
- PXS : instance size : 4
- PXS : processing script class arrowturret
- PXS : instance size : 4
- PXS : processing script class particle
- PXS : instance size : 4
- PXS : processing script class airstrikebase
- PXS : processing script class bowlingball
- PXS : instance size : 4
- PXS : processing script class bbstrike
- PXS : instance size : 4
- PXS : processing script class magnet
- PXS : instance size : 4
- PXS : processing script class bunkerbuster
- PXS : instance size : 4
- PXS : processing script class fan
- PXS : instance size : 4
- PXS : processing script class paratest
- PXS : instance size : 4
- PXS : processing script class texbeam
- PXS : instance size : 4
- PXS : processing script class lightningstrike
- PXS : instance size : 4
- PXS : processing script class bullet
- PXS : processing script class sentrygun
- PXS : instance size : 4
- PXS : processing script class tazer
- PXS : instance size : 8
- PXS : Linking group 2..
- PXS : Processing overrides
- PXS : Making overrides
- PXS : Making overidde of FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of CMissile@PCCObject@PCCWeaponLaunch@PCCShootDesc@
- PXS : by ^CMissile@PCCObject@PCCWeaponLaunch@PCCShootDesc@
- PXS : VFT 005E8388, class : CMissile
- PXS : work3
- PXS : Detected derived from CMissile to WindNade
- PXS : Detected derived from CMissile to GravityNade
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of CMine@PCCObject@PCCMineParams@PCCShootDesc@Bi
- PXS : by ^CMine@PCCObject@PCCMineParams@PCCShootDesc@Bi
- PXS : VFT 005E8338, class : CMine
- PXS : work3
- PXS : Detected derived from CMine to StickyMine
- PXS : Detected derived from CMine to CBowlingBall
- PXS : Detected derived from CMine to CMagnet
- PXS : Detected derived from CMine to CMagnetMissile
- PXS : Detected derived from CMine to PxBunkerBuster
- PXS : Detected derived from CMine to PxFan
- PXS : Detected derived from CMine to PxSentryGun
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8338, class : CMine
- PXS : work3
- PXS : Detected derived from CMine to StickyMine
- PXS : Detected derived from CMine to CBowlingBall
- PXS : Detected derived from CMine to CMagnet
- PXS : Detected derived from CMine to CMagnetMissile
- PXS : Detected derived from CMine to PxBunkerBuster
- PXS : Detected derived from CMine to PxFan
- PXS : Detected derived from CMine to PxSentryGun
- PXS : Making overidde of SetCurrentTeam@i
- PXS : by ^SetCurrentTeam@i
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of Free@B
- PXS : by ^Free@B
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of CGObject@PCCObject@ii
- PXS : by ^CGObject@PCCObject@ii
- PXS : VFT 005E8140, class : CGObject
- PXS : work3
- PXS : Detected derived from CGObject to CCrate
- PXS : Detected derived from CGObject to CMine
- PXS : Detected derived from CGObject to CWorm
- PXS : Detected derived from CGObject to COilDrum
- PXS : Detected derived from CGObject to CArrow
- PXS : Detected derived from CGObject to CMissile
- PXS : Detected derived from CGObject to CTouchSensor
- PXS : Detected derived from CGObject to StickyMine
- PXS : Detected derived from CGObject to MovingOilDrum
- PXS : Detected derived from CGObject to WindNade
- PXS : Detected derived from CGObject to GravityNade
- PXS : Detected derived from CGObject to CTurretBase
- PXS : Detected derived from CGObject to CMineTurret
- PXS : Detected derived from CGObject to CArrowTurret
- PXS : Detected derived from CGObject to CBowlingBall
- PXS : Detected derived from CGObject to CMagnet
- PXS : Detected derived from CGObject to CMagnetMissile
- PXS : Detected derived from CGObject to PxBunkerBuster
- PXS : Detected derived from CGObject to PxFan
- PXS : Detected derived from CGObject to PxSentryGun
- PXS : Making overidde of CheckCollisionEx@PCCGObject@FFPCCColMask@i
- PXS : by ^CheckCollisionEx@PCCGObject@FFPCCColMask@i
- PXS : VFT 005E80E0, class : CEnv
- PXS : work3
- PXS : Making overidde of ^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of SetState@eEObjState@
- PXS : by ^SetState@eEObjState@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of RenderLabels@
- PXS : by ^RenderLabels@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of RenderCrosshair@
- PXS : by ^RenderCrosshair@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of AddSprite@FFFiiF
- PXS : by ^AddSprite@FFFiiF
- PXS : VFT 00000000, class : CDDQueue
- PXS : work3
- PXS : Making overidde of ForceFocus@FF
- PXS : by ^ForceFocus@FF
- PXS : VFT 005EDD30, class : CObject
- PXS : work3
- PXS : Detected derived from CObject to CTurnGame
- PXS : Detected derived from CObject to CGObject
- PXS : Detected derived from CObject to CCrate
- PXS : Detected derived from CObject to CMine
- PXS : Detected derived from CObject to CWorm
- PXS : Detected derived from CObject to COilDrum
- PXS : Detected derived from CObject to CFire
- PXS : Detected derived from CObject to CGas
- PXS : Detected derived from CObject to CArrow
- PXS : Detected derived from CObject to CTeam
- PXS : Detected derived from CObject to CFilter
- PXS : Detected derived from CObject to CMissile
- PXS : Detected derived from CObject to CTouchSensorParent
- PXS : Detected derived from CObject to CTouchSensor
- PXS : Detected derived from CObject to StickyMine
- PXS : Detected derived from CObject to MovingOilDrum
- PXS : Detected derived from CObject to WindNade
- PXS : Detected derived from CObject to GravityNade
- PXS : Detected derived from CObject to CTurretBase
- PXS : Detected derived from CObject to CMineTurret
- PXS : Detected derived from CObject to CArrowTurret
- PXS : Detected derived from CObject to PxParticleManager
- PXS : Detected derived from CObject to PxParticle
- PXS : Detected derived from CObject to PxAirstrike
- PXS : Detected derived from CObject to CBowlingBall
- PXS : Detected derived from CObject to PxBowlingBallStrike
- PXS : Detected derived from CObject to CMagnet
- PXS : Detected derived from CObject to CMagnetMissile
- PXS : Detected derived from CObject to PxBunkerBusterStrike
- PXS : Detected derived from CObject to PxBunkerBuster
- PXS : Detected derived from CObject to PxWindManager
- PXS : Detected derived from CObject to PxFan
- PXS : Detected derived from CObject to PxDeadWormManager
- PXS : Detected derived from CObject to PxDeadWorm
- PXS : Detected derived from CObject to PxLightningStrike
- PXS : Detected derived from CObject to PxSentryGun
- PXS : Detected derived from CObject to CTazerDamage
- PXS : Detected derived from CObject to CTazerShot
- PXS : Making overidde of LookAtMe@FFi
- PXS : by ^LookAtMe@FFi
- PXS : VFT 005E8140, class : CGObject
- PXS : work3
- PXS : Detected derived from CGObject to CCrate
- PXS : Detected derived from CGObject to CMine
- PXS : Detected derived from CGObject to CWorm
- PXS : Detected derived from CGObject to COilDrum
- PXS : Detected derived from CGObject to CArrow
- PXS : Detected derived from CGObject to CMissile
- PXS : Detected derived from CGObject to CTouchSensor
- PXS : Detected derived from CGObject to StickyMine
- PXS : Detected derived from CGObject to MovingOilDrum
- PXS : Detected derived from CGObject to WindNade
- PXS : Detected derived from CGObject to GravityNade
- PXS : Detected derived from CGObject to CTurretBase
- PXS : Detected derived from CGObject to CMineTurret
- PXS : Detected derived from CGObject to CArrowTurret
- PXS : Detected derived from CGObject to CBowlingBall
- PXS : Detected derived from CGObject to CMagnet
- PXS : Detected derived from CGObject to CMagnetMissile
- PXS : Detected derived from CGObject to PxBunkerBuster
- PXS : Detected derived from CGObject to PxFan
- PXS : Detected derived from CGObject to PxSentryGun
- PXS : Making overidde of ^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of ^CMine@PCCObject@PCCMineParams@PCCShootDesc@Bi
- PXS : by ^^CMine@PCCObject@PCCMineParams@PCCShootDesc@Bi
- PXS : VFT 005E8338, class : CMine
- PXS : work3
- PXS : Detected derived from CMine to StickyMine
- PXS : Detected derived from CMine to CBowlingBall
- PXS : Detected derived from CMine to CMagnet
- PXS : Detected derived from CMine to CMagnetMissile
- PXS : Detected derived from CMine to PxBunkerBuster
- PXS : Detected derived from CMine to PxFan
- PXS : Detected derived from CMine to PxSentryGun
- PXS : Making overidde of ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8338, class : CMine
- PXS : work3
- PXS : Detected derived from CMine to StickyMine
- PXS : Detected derived from CMine to CBowlingBall
- PXS : Detected derived from CMine to CMagnet
- PXS : Detected derived from CMine to CMagnetMissile
- PXS : Detected derived from CMine to PxBunkerBuster
- PXS : Detected derived from CMine to PxFan
- PXS : Detected derived from CMine to PxSentryGun
- PXS : Making overidde of Render@
- PXS : by ^Render@
- PXS : VFT 005E8338, class : CMine
- PXS : work3
- PXS : Detected derived from CMine to StickyMine
- PXS : Detected derived from CMine to CBowlingBall
- PXS : Detected derived from CMine to CMagnet
- PXS : Detected derived from CMine to CMagnetMissile
- PXS : Detected derived from CMine to PxBunkerBuster
- PXS : Detected derived from CMine to PxFan
- PXS : Detected derived from CMine to PxSentryGun
- PXS : Making overidde of OnSink@
- PXS : by ^OnSink@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ExplodeAt@FF
- PXS : by ^ExplodeAt@FF
- PXS : VFT 005E8388, class : CMissile
- PXS : work3
- PXS : Detected derived from CMissile to WindNade
- PXS : Detected derived from CMissile to GravityNade
- PXS : Making overidde of ^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ApplyBitmap@iiiiPCCBitmap@PCCBitmap@ii
- PXS : by ^ApplyBitmap@iiiiPCCBitmap@PCCBitmap@ii
- PXS : VFT 00608BB8, class : CLandscape
- PXS : work3
- PXS : Making overidde of CArrow@PCCObject@PiPCCShootDesc@
- PXS : by ^CArrow@PCCObject@PiPCCShootDesc@
- PXS : VFT 005E80E8, class : CArrow
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E80E8, class : CArrow
- PXS : work3
- PXS : Making overidde of ^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^SetCurrentTeam@i
- PXS : by ^^SetCurrentTeam@i
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of ^^CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of SetAnimEx@iF
- PXS : by ^SetAnimEx@iF
- PXS : VFT 005E8038, class : CSpriteAnim
- PXS : work3
- PXS : Making overidde of ^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^SetCurrentTeam@i
- PXS : by ^^^SetCurrentTeam@i
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of ^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^SetAnimEx@iF
- PXS : by ^^SetAnimEx@iF
- PXS : VFT 005E8038, class : CSpriteAnim
- PXS : work3
- PXS : Making overidde of ^^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^^^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of Free@B
- PXS : by ^Free@B
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^SetCurrentTeam@i
- PXS : by ^^^^SetCurrentTeam@i
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of ^^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^SetCurrentTeam@i
- PXS : by ^^^^^SetCurrentTeam@i
- PXS : VFT 005EDD14, class : CTurnGame
- PXS : work3
- PXS : Making overidde of ^^^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : by ^^^^^^^CWorm@PCCObject@iiPCCWormParams@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by ^^^^^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of ^^^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : by ^^^^^^^^^^^^^FireFinal@PCCWeapon@PCCShootDesc@
- PXS : VFT 005E8490, class : CWorm
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BC3C, class : CTouchSensor
- PXS : work3
- PXS : Making overidde of Reflect@PCCGObject@i
- PXS : by Reflect@PCCGObject@i
- PXS : VFT 0A93BC3C, class : CTouchSensor
- PXS : work3
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BC94, class : StickyMine
- PXS : work3
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93BC94, class : StickyMine
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BCDC, class : MovingOilDrum
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BDBC, class : CTurretBase
- PXS : Detected derived from CTurretBase to CMineTurret
- PXS : Detected derived from CTurretBase to CArrowTurret
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BE9C, class : PxParticleManager
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BEBC, class : PxParticle
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BEDC, class : PxAirstrike
- PXS : Detected derived from PxAirstrike to PxBowlingBallStrike
- PXS : Detected derived from PxAirstrike to PxBunkerBusterStrike
- PXS : Making overidde of Free@B
- PXS : by Free@B
- PXS : VFT 0A93BEFC, class : CBowlingBall
- PXS : work3
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BEFC, class : CBowlingBall
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93BEFC, class : CBowlingBall
- PXS : Making overidde of ^Render@
- PXS : by Render@
- PXS : VFT 0A93BEFC, class : CBowlingBall
- PXS : work3
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BF6C, class : CMagnet
- PXS : Detected derived from CMagnet to CMagnetMissile
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93BF6C, class : CMagnet
- PXS : Detected derived from CMagnet to CMagnetMissile
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C01C, class : PxBunkerBuster
- PXS : Making overidde of DoExplosion@FFiiii
- PXS : by DoExplosion@FFiiii
- PXS : VFT 0A93C01C, class : PxBunkerBuster
- PXS : work3
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93C01C, class : PxBunkerBuster
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C064, class : PxWindManager
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C084, class : PxFan
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93C084, class : PxFan
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C0FC, class : PxDeadWorm
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C118, class : PxLightningStrike
- PXS : Making overidde of ^^Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C13C, class : PxSentryGun
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93C13C, class : PxSentryGun
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C188, class : CTazerDamage
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93C1A4, class : CTazerShot
- PXS : Making overidde of ShootAtEnemy@
- PXS : by ShootAtEnemy@
- PXS : VFT 0A93BE08, class : CMineTurret
- PXS : work3
- PXS : Making overidde of AimToEnemy@
- PXS : by AimToEnemy@
- PXS : VFT 0A93BE54, class : CArrowTurret
- PXS : work3
- PXS : Making overidde of ShootAtEnemy@
- PXS : by ShootAtEnemy@
- PXS : VFT 0A93BE54, class : CArrowTurret
- PXS : Making overidde of DropBomb@
- PXS : by DropBomb@
- PXS : VFT 0A93BF48, class : PxBowlingBallStrike
- PXS : work3
- PXS : Making overidde of RenderPlane@
- PXS : by RenderPlane@
- PXS : VFT 0A93BF48, class : PxBowlingBallStrike
- PXS : work3
- PXS : Making overidde of Collide@PCCGObject@i
- PXS : by Collide@PCCGObject@i
- PXS : VFT 0A93BFB4, class : CMagnetMissile
- PXS : work3
- PXS : Making overidde of Message@PCCObject@eEMType@iPCCMessageData@
- PXS : by Message@PCCObject@eEMType@iPCCMessageData@
- PXS : VFT 0A93BFB4, class : CMagnetMissile
- PXS : work3
- PXS : Making overidde of DropBomb@
- PXS : by DropBomb@
- PXS : VFT 0A93C000, class : PxBunkerBusterStrike
- PXS : Making overidde of RenderPlane@
- PXS : by RenderPlane@
- PXS : VFT 0A93C000, class : PxBunkerBusterStrike
- PXS : Linking..
- PXS : Updating class sizes..
- PXS : Compiled from 0A840004
- PXS : Code size - 129,91 KB (12,991%)
- PXS : Variables size - 11,69 KB (1,169%)
- PXS : HKLIBEX extra memory size - 9,13 KB (0,713%)
- PXS : Linked
- PXS : ESS has been initialized
- Loading hi\bazooka.img
- Loading hi\bazooka.img
- Loading hi\hmissile.img
- Loading hi\mortar.img
- Loading hi\pigeon.img
- Loading hi\launch.img
- Loading hi\grenade.img
- Loading hi\cluster.img
- Loading hi\banana.img
- Loading hi\axe.img
- Loading hi\quake.img
- Loading hi\shotgun.img
- Loading hi\handgun.img
- Loading hi\uzi.img
- Loading hi\minigun.img
- Loading hi\longbow.img
- Loading hi\firepnch.img
- Loading hi\dragball.img
- Loading hi\kamikaze.img
- Loading hi\suicide.img
- Loading hi\prod.img
- Loading hi\dynamite.img
- Loading hi\mine.img
- Loading hi\sheep.img
- Loading hi\sprsheep.img
- Loading hi\aqua.img
- Loading hi\mole.img
- Loading hi\airstrke.img
- Loading hi\firestrk.img
- Loading hi\postal.img
- Loading hi\minestrk.img
- Loading hi\molestrk.img
- Loading hi\blwtorch.img
- Loading hi\drill.img
- Loading hi\girder.img
- Loading hi\baseball.img
- Loading hi\girders.img
- Loading hi\rope.img
- Loading hi\bungee.img
- Loading hi\parachut.img
- Loading hi\teleport.img
- Loading hi\scales.img
- Loading hi\sbanana.img
- Loading hi\hgrenade.img
- Loading hi\thrower.img
- Loading hi\tamborin.img
- Loading hi\mbbomb.img
- Loading hi\petrolbm.img
- Loading hi\skunk.img
- Loading hi\mingvase.img
- Loading hi\shpstrke.img
- Loading hi\carpet.img
- Loading hi\cow.img
- Loading hi\oldwoman.img
- Loading hi\donkey.img
- Loading hi\nuke.img
- Loading hi\armagedn.img
- Loading hi\skipgo.img
- Loading hi\surender.img
- Loading hi\select.img
- Loading hi\freeze.img
- Loading hi\bullet.img
- Loading hi\jetpack.img
- Loading hi\gravity.img
- Loading hi\speed.img
- Loading hi\laser.img
- Loading hi\invisibl.img
- Loading hi\damagex2.img
- Loading hi\cratespy.img
- Loading hi\cratespy.img
- Loading hi\cratespy.img
- Loading hi\bazooka.img
- Weapon from lib
- Loading ico_magmissile.png
- Loading done
- Loading hi\hmissile.img
- Loading hi\mortar.img
- Loading hi\pigeon.img
- Loading hi\launch.img
- Weapon from lib
- Loading gravitynade.png
- Loading done
- Weapon from lib
- Loading WindyNade.png
- Loading done
- Weapon from lib
- Loading oildrum.png
- Loading done
- Weapon from lib
- Loading ic_telenade.png
- Loading done
- Weapon from lib
- Loading stickymine.png
- Loading done
- Weapon from lib
- Loading ico_tazer.png
- Loading done
- Loading hi\handgun.img
- Loading hi\uzi.img
- Loading hi\minigun.img
- Loading hi\longbow.img
- Loading hi\firepnch.img
- Loading hi\dragball.img
- Loading hi\kamikaze.img
- Loading hi\suicide.img
- Loading hi\prod.img
- Weapon from lib
- Loading ico_bowling.png
- Loading done
- Weapon from lib
- Loading ico_sentrygun.png
- Loading done
- Weapon from lib
- Loading ico_magnet.png
- Loading done
- Weapon from lib
- Loading ico_fan.png
- Loading done
- Loading hi\aqua.img
- Loading hi\mole.img
- Weapon from lib
- Loading ico_bunkerbuster.png
- Loading done
- Weapon from lib
- Loading ico_superbunkerbuster.png
- Loading done
- Weapon from lib
- Loading ico_bbstrike.png
- Loading done
- Loading hi\minestrk.img
- Loading hi\molestrk.img
- Loading hi\blwtorch.img
- Loading hi\drill.img
- Loading hi\girder.img
- Loading hi\baseball.img
- Loading hi\girders.img
- Loading hi\rope.img
- Loading hi\bungee.img
- Loading hi\parachut.img
- Loading hi\teleport.img
- Weapon from lib
- Loading ico_glider.png
- Loading done
- Loading hi\sbanana.img
- Loading hi\hgrenade.img
- Loading hi\thrower.img
- Loading hi\tamborin.img
- Loading hi\mbbomb.img
- Weapon from lib
- Loading img_mineturret.png
- Loading done
- Weapon from lib
- Loading img_balturret.png
- Loading done
- Weapon from lib
- Loading ico_lightningstrike.png
- Loading done
- Loading hi\shpstrke.img
- Loading hi\carpet.img
- Loading hi\cow.img
- Loading hi\oldwoman.img
- Loading hi\donkey.img
- Loading hi\nuke.img
- Loading hi\armagedn.img
- Loading hi\skipgo.img
- Loading hi\surender.img
- Loading hi\select.img
- Loading hi\freeze.img
- Loading hi\bullet.img
- Loading hi\jetpack.img
- Loading hi\gravity.img
- Loading hi\speed.img
- Loading hi\laser.img
- Loading hi\invisibl.img
- Loading hi\damagex2.img
- Loading hi\cratespy.img
- Loading hi\cratespy.img
- Loading hi\cratespy.img
- Loading done 4 all
- SchemeMan initialized successfully!
- Scheme is changed
- Loaded
- Done
- Player 0 joined
- Player 0 received PX message
- Sending message : SYS::ALL:This server uses Project X 0.8.0.3104. Official Project X website is px.worms2d.info !
- Sending message : SYS::ALL:You don't have Project X installed!
- Setting player : 1 to 3 handle 67692912
- li pair 0 - 1
- Setting data : 3 to 67168352 from 3
- DONE
- li pair 0 - 1
- li pair 1 - -1
- li pair 2 - -1
- li pair 3 - -1
- li pair 4 - -1
- li pair 5 - -1
- Player 1is reset
- PXhalg
- PXhalf
- WA_GPN : 1
- li pair 0 - 1
- LI : 1
- out MEDVEDxEvilPunk
- TScheme changed!
- TPX_NecFileList: Saving 20 files
- Setting player : 1 to 3 handle 67692912
- li pair 0 - 1
- Setting data : 3 to 67168352 from 3
- DONE
- li pair 0 - 1
- li pair 1 - -1
- li pair 2 - -1
- li pair 3 - -1
- li pair 4 - -1
- li pair 5 - -1
- Player 1 joined
- Player 1 received PX message
- Sending message : SYS::ALL:This server uses Project X 0.8.0.3104. Official Project X website is px.worms2d.info !
- Sending message : SYS::ALL:You don't have Project X installed!
- Setting player : 2 to 3 handle 67692912
- li pair 1 - 2
- Setting data : 3 to 67168392 from 3
- DONE
- li pair 0 - 1
- li pair 1 - 2
- li pair 2 - -1
- li pair 3 - -1
- li pair 4 - -1
- li pair 5 - -1
- Player 2 joined
- Player 2 received PX message
- Sending message : SYS::ALL:This server uses Project X 0.8.0.3104. Official Project X website is px.worms2d.info !
- Sending message : SYS::ALL:You don't have Project X installed!
- Setting player : 3 to 3 handle 67692912
- li pair 2 - 3
- Setting data : 3 to 67168392 from 3
- DONE
- li pair 0 - 1
- li pair 1 - 2
- li pair 2 - 3
- li pair 3 - -1
- li pair 4 - -1
- li pair 5 - -1
- WA_GPN : 1
- li pair 0 - 1
- LI : 1
- out MEDVEDxEvilPunk
- Setting player : 1 to 0 handle 67692912
- li pair 0 - 1
- Setting data : 0 to 67181560 from 0
- DONE
- li pair 0 - 1
- li pair 1 - 2
- li pair 2 - 3
- li pair 3 - -1
- li pair 4 - -1
- li pair 5 - -1
- Player 6is reset
- Player 0is reset
- Player 1is reset
- Player 2is reset
- Player 3is reset
- Player 4is reset
- Player 5is reset
- Server Form Destroyed
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement