Skip to content

Commit

Permalink
feat: Angry Hobo, CarIsBroken, OhNoMyWheel
Browse files Browse the repository at this point in the history
  • Loading branch information
AthallahDzaki committed Aug 20, 2024
1 parent bcb913c commit 8339fce
Show file tree
Hide file tree
Showing 7 changed files with 411 additions and 2 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ include(cmake/uWebSockets.cmake)
include(cmake/minhook.cmake)
include(cmake/efsw.cmake)

include(cmake/gta3.cmake)
include(cmake/gtaVC.cmake)
# include(cmake/gta3.cmake)
# include(cmake/gtaVC.cmake)
include(cmake/gtaSA.cmake)

if(DEFINED ENV{GITHUB_SHA})
Expand Down
94 changes: 94 additions & 0 deletions src/gtasa/effects/custom/ped/AngryHoboEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "effects/OneTimeEffect.h"
#include "util/Globals.h"

#include <CStreaming.h>
#include <CCivilianPed.h>
#include <CPopulation.h>
#include <CPlayerPed.h>
#include <CWorld.h>
#include <CVector.h>
#include <CPed.h>
#include <extensions/ScriptCommands.h>
#include <CPickups.h>

#include "util/HoboManager.h"

using namespace plugin;

class SpawnAngryHobo : public OneTimeEffect
{
int hoboType = 0; // 0 - DE, 1 - Rocket, 2 - Homing Rocket, 3 - Minigun, 4 - Spawn Hydra
eWeaponType weaponType = WEAPON_BRASSKNUCKLE;

public:
SpawnAngryHobo (int type) : hoboType (type) {
switch (type) {
case 0: weaponType = WEAPON_DESERT_EAGLE; break;
case 1: weaponType = WEAPON_RLAUNCHER; break;
case 2: weaponType = WEAPON_RLAUNCHER_HS; break;
case 3: weaponType = WEAPON_MINIGUN; break;
}
}

void
OnStart (EffectInstance *inst) override
{
CPlayerPed *player = FindPlayerPed ();
if (!player) return;

CVector position
= player->TransformFromObjectSpace (CVector (0.0f, -5.0f, 3.0f));

int modelID = 230; // hobo
CStreaming::RequestModel(modelID, 0);
CStreaming::LoadAllRequestedModels(false);
CPed *ped = new CCivilianPed(PED_TYPE_CIVMALE, modelID);
if (ped) {
ped->SetCharCreatedBy(2); // SCM Ped cannot be Removed!
ped->SetPosn(position);
ped->SetOrientation(0.0f, 0.0f, 0.0f);
CWorld::Add(ped);
ped->m_nWeaponShootingRate = 99999;
ped->m_nWeaponAccuracy = 99999;
ped->m_fHealth = hoboType == 3 ? 5000.0f : 1000.0f;

// Only Explosion and Ramp can kill normal hobo
ped->m_nPhysicalFlags.bBulletProof = true;
ped->m_nPhysicalFlags.bFireProof = true;
ped->m_nPhysicalFlags.bMeleeProof = true;
if(hoboType >= 1) {
ped->m_nPhysicalFlags.bExplosionProof = true;
}
if(hoboType >= 2) {
ped->m_nPhysicalFlags.bCollisionProof = true;
}
// How to Kill the Undead Hobo (Collsion proof and Explosion Proof)?
// 1. Delete from the game, (Need Global Variable)
// 2. Use Parachute and use Stinklikeabee cheat to kill the hobo

auto model = CPickups::ModelForWeapon(weaponType);
CStreaming::RequestModel(model, 2);
CStreaming::LoadAllRequestedModels(false);
ped->GiveWeapon(weaponType, 99999, false);
ped->SetCurrentWeapon(weaponType);
CStreaming::SetModelIsDeletable(model);

ped->PositionAnyPedOutOfCollision();
Command<eScriptCommands::COMMAND_SET_CHAR_RELATIONSHIP> (ped, 4, ePedType::PED_TYPE_PLAYER1);
}
HoboManager::AddAngryHobo(ped);
}
};

enum {
ANGRY_HOBO = 0,
CRAZY_HOBO,
ULTRA_CRAZY_HOBO,
GIGACHAD_HOBO,
PILOT_HOBO // Spawn Angry Hobo with Hydra :)
};

DEFINE_EFFECT (SpawnAngryHobo, "effect_spawn_angry_hobo", 0, ANGRY_HOBO);
DEFINE_EFFECT (SpawnAngryHobo, "effect_spawn_crazy_hobo", 0, CRAZY_HOBO);
DEFINE_EFFECT (SpawnAngryHobo, "effect_spawn_ultra_crazy_hobo", 0, ULTRA_CRAZY_HOBO);
DEFINE_EFFECT (SpawnAngryHobo, "effect_spawn_gigachad_hobo", 0, GIGACHAD_HOBO);
73 changes: 73 additions & 0 deletions src/gtasa/effects/custom/ped/RemoveAngryHoboEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "effects/OneTimeEffect.h"

#include <CPlayerPed.h>
#include "util/HoboManager.h"

using namespace plugin;

class RemoveAngryHobo : public OneTimeEffect
{
int removeType = 0; // 0 - Random, 1 - Nearest, 2 - Farthest, 3 - All
public:
RemoveAngryHobo (int type) : removeType (type) {}

bool
CanActivate () override
{
return HoboManager::angryHobo.size () > 0;
}

void
OnStart (EffectInstance *inst) override
{
switch (removeType) {
case 0: HoboManager::RemoveRandomAngryHobo (); break;
case 1: {
CPed *player = FindPlayerPed ();
if (player) {
CPed *nearest = nullptr;
float nearestDist = 999999.0f;
for (CPed *ped : HoboManager::angryHobo) {
if (ped) {
float dist = DistanceBetweenPoints (player->GetPosition (), ped->GetPosition ());
if (dist < nearestDist) {
nearest = ped;
nearestDist = dist;
}
}
}
if (nearest) {
HoboManager::RemoveAngryHobo (nearest);
}
}
break;
}
case 2: {
CPed *player = FindPlayerPed ();
if (player) {
CPed *farthest = nullptr;
float farthestDist = 0.0f;
for (CPed *ped : HoboManager::angryHobo) {
if (ped) {
float dist = DistanceBetweenPoints (player->GetPosition (), ped->GetPosition ());
if (dist > farthestDist) {
farthest = ped;
farthestDist = dist;
}
}
}
if (farthest) {
HoboManager::RemoveAngryHobo (farthest);
}
}
break;
}
case 3: HoboManager::RemoveAllAngryHobo (); break;
}
}
};

DEFINE_EFFECT (RemoveAngryHobo, "effect_remove_random_angry_hobo", 0);
DEFINE_EFFECt (RemoveAngryHobo, "effect_remove_nearest_angry_hobo", 1);
DEFINE_EFFECT (RemoveAngryHobo, "effect_remove_farthest_angry_hobo", 2);
DEFINE_EFFECT (RemoveAngryHobo, "effect_remove_all_angry_hobo", 3);
82 changes: 82 additions & 0 deletions src/gtasa/effects/custom/vehicle/CarIsBrokenEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "util/EffectBase.h"
#include "util/GameUtil.h"
#include "util/GenericUtil.h"

class CarIsBrokenEffect : public EffectBase
{
int wait = 0;
bool doBroken = true;

public:
void
OnStart (EffectInstance *inst) override
{
wait = 0;
doBroken = true;
}

void
OnEnd (EffectInstance *inst) override
{
FixDoor();
}

void
OnTick (EffectInstance *inst) override
{
wait -= (int) GenericUtil::CalculateTick ();
if (wait > 0) return;

GameUtil::SetVehiclesToRealPhysics ();

doBroken = !doBroken;
if (doBroken)
{
BrokeDoor ();
wait = 25;
}
else
{
FixDoor ();
wait = 50;
}
}

void
BrokeDoor ()
{
for (CVehicle *vehicle : CPools::ms_pVehiclePool)
{
if (vehicle->m_nVehicleSubClass == VEHICLE_AUTOMOBILE || vehicle->m_nVehicleSubClass == VEHICLE_MTRUCK)
{
CAutomobile *car = reinterpret_cast<CAutomobile *> (vehicle);
car->PopDoor (eCarNodes::CAR_DOOR_LF, eDoors::DOOR_FRONT_LEFT, true);
car->PopDoor (eCarNodes::CAR_DOOR_RF, eDoors::DOOR_FRONT_RIGHT, true);
car->PopDoor (eCarNodes::CAR_DOOR_LR, eDoors::DOOR_REAR_LEFT, true);
car->PopDoor (eCarNodes::CAR_DOOR_RR, eDoors::DOOR_REAR_RIGHT, true);
car->PopDoor (eCarNodes::CAR_BONNET, eDoors::BONNET, true);
car->PopDoor (eCarNodes::CAR_BOOT, eDoors::BOOT, true);
}
}
}

void
FixDoor ()
{
for (CVehicle *vehicle : CPools::ms_pVehiclePool)
{
if (vehicle->m_nVehicleSubClass == VEHICLE_AUTOMOBILE || vehicle->m_nVehicleSubClass == VEHICLE_MTRUCK)
{
CAutomobile *car = reinterpret_cast<CAutomobile *> (vehicle);
car->FixDoor (eCarNodes::CAR_DOOR_LF, eDoors::DOOR_FRONT_LEFT);
car->FixDoor (eCarNodes::CAR_DOOR_RF, eDoors::DOOR_FRONT_RIGHT);
car->FixDoor (eCarNodes::CAR_DOOR_LR, eDoors::DOOR_REAR_LEFT);
car->FixDoor (eCarNodes::CAR_DOOR_RR, eDoors::DOOR_REAR_RIGHT);
car->FixDoor (eCarNodes::CAR_BONNET, eDoors::BONNET);
car->FixDoor (eCarNodes::CAR_BOOT, eDoors::BOOT);
}
}
}
};

DEFINE_EFFECT (CarIsBrokenEffect, "effect_car_is_broken", 0);
80 changes: 80 additions & 0 deletions src/gtasa/effects/custom/vehicle/OhNoMyWheelEffect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "effects/OneTimeEffect.h"
#include "util/GameUtil.h"
#include "util/GenericUtil.h"
#include "util/GlobalRenderer.h"

class OhNoMyWheel : public OneTimeEffect
{
public:
bool
CanActivate () override
{
CVehicle *vehicle = FindPlayerVehicle (-1, false);
return (vehicle && (vehicle->m_nVehicleSubClass == VEHICLE_AUTOMOBILE || vehicle->m_nVehicleSubClass == VEHICLE_QUAD) && vehicle->m_nModelIndex != MODEL_RHINO);
}

void
OnStart (EffectInstance *inst) override
{
CVehicle *vehicle = FindPlayerVehicle (-1, false);
DetachThisWheel(vehicle, eCarNodes::CAR_WHEEL_LF, 0, false);
DetachThisWheel(vehicle, eCarNodes::CAR_WHEEL_LB, 1, true);
DetachThisWheel(vehicle, eCarNodes::CAR_WHEEL_RF, 2, false);
DetachThisWheel(vehicle, eCarNodes::CAR_WHEEL_RB, 3, true);
}

void
HideAllAtomics(RwFrame *frame)
{
if (!rwLinkListEmpty(&frame->objectList))
{
RwObjectHasFrame * atomic;

RwLLLink * current = rwLinkListGetFirstLLLink(&frame->objectList);
RwLLLink * end = rwLinkListGetTerminator(&frame->objectList);

current = rwLinkListGetFirstLLLink(&frame->objectList);
while (current != end) {
atomic = rwLLLinkGetData(current, RwObjectHasFrame, lFrame);
atomic->object.flags &= ~0x4; // clear

current = rwLLLinkGetNext(current);
}
}
return;
}

bool
IsNotLastWheel(CAutomobile *automobile, int wheelId)
{
for (int i = 0; i < 4; ++i)
{
if (i != wheelId && automobile->m_damageManager.m_anWheelsStatus[i] != 2)
{
return true;
}
}
return false;
}

void
DetachThisWheel(CVehicle *vehicle, int wheelNode, int wheelId, bool isRear)
{
CAutomobile *automobile = reinterpret_cast<CAutomobile*>(vehicle);
if (vehicle->IsComponentPresent(wheelNode) && IsNotLastWheel(automobile, wheelId))
{
if (wheelId != -1)
{
if (!isRear)
{
automobile->m_damageManager.SetWheelStatus(wheelId, 2);
}
}
automobile->SpawnFlyingComponent(wheelNode, 1);
HideAllAtomics(automobile->m_aCarNodes[wheelNode]);
}
}

};

DEFINE_EFFECT (OhNoMyWheel, "effect_oh_no_my_wheel", 0);
Loading

0 comments on commit 8339fce

Please sign in to comment.