Ares
Functions

Hooks.Trenches.cpp File Reference

#include "Body.h"
#include "../BuildingType/Body.h"
#include "../Techno/Body.h"
#include "../../Misc/Network.h"
#include <SpecificStructures.h>
#include <ScenarioClass.h>
#include <InfantryClass.h>
#include <CellClass.h>
#include <cmath>

Functions

 DEFINE_HOOK (457D58, BuildingClass_CanBeOccupied_SpecificOccupiers, 6)
 DEFINE_HOOK (441F12, BuildingClass_Destroy_RubbleYell, 6)
 DEFINE_HOOK (441F2C, BuildingClass_Destroy_KickOutOfRubble, 5)
 DEFINE_HOOK (44725F, BuildingClass_GetCursorOverObject_TargetABuilding, 5)
 DEFINE_HOOK (443414, BuildingClass_ClickedAction, 6)
 DEFINE_HOOK (4494D2, BuildingClass_IsSellable, 6)
 DEFINE_HOOK (52297F, InfantryClass_GarrisonBuilding_OccupierEntered, 5)
 DEFINE_HOOK (4586CA, BuildingClass_KillOccupiers_EachOccupierKilled, 6)
 DEFINE_HOOK (4581CD, BuildingClass_UnloadOccupants_AllOccupantsHaveLeft, 6)
 DEFINE_HOOK (458729, BuildingClass_KillOccupiers_AllOccupantsKilled, 6)
 DEFINE_HOOK (448401, BuildingClass_ChangeOwnership_TrenchEVA, 6)

Function Documentation

DEFINE_HOOK ( 457D58  ,
BuildingClass_CanBeOccupied_SpecificOccupiers  ,
 
)
{
        GET(BuildingClass *, pThis, ESI);
        GET(InfantryClass *, pInf, EDI);
        BuildingTypeExt::ExtData* pBuildTypeExt = BuildingTypeExt::ExtMap.Find(pThis->Type);
        bool can_occupy = false;

        if(pInf->Type->Occupier) {
                bool isFull = (pThis->GetOccupantCount() == pThis->Type->MaxNumberOccupants);
                bool isEmpty = (pThis->GetOccupantCount() == 0); // yes, yes, !pThis->GetOccupantCount() - leave it this way for semantics :P
                bool isIneligible = (pThis->IsRedHP() || pInf->IsMindControlled());
                bool isNeutral = pThis->Owner->IsNeutral();
                bool isRaidable = (pBuildTypeExt->BunkerRaidable && isEmpty); // if it's not empty, it cannot be raided anymore, 'cause it already was
                bool sameOwner = (pThis->Owner == pInf->Owner);

                bool allowedOccupier = pBuildTypeExt->CanBeOccupiedBy(pInf);

                if(!isFull && !isIneligible && allowedOccupier) {
                /*      The building switches owners after the first occupant enters,
                        so this check should not interfere with the player who captured it,
                        only prevent others from entering it while it's occupied. (Bug #699) */
                        can_occupy = sameOwner ? true : (isNeutral || isRaidable);
                }
        }

/*
// original code replaced by this hook
        if(pInf->Occupier) {
                if ( pThis->Owner != pInf->Owner && !pThis->Owner->Country->MultiplayPassive
                        || pThis->GetOccupantCount() == pThis->BuildingType->MaxNumberOccupants
                        || pThis->IsRedHP()
                        || pInf->IsMindControlled() )
                        return 0;
        }
        return 1;
*/

        return can_occupy ? 0x457DD5 : 0x457DA3;
}
DEFINE_HOOK ( 448401  ,
BuildingClass_ChangeOwnership_TrenchEVA  ,
 
)
{
        GET(BuildingClass *, pBld, ESI);
        GET(HouseClass *, pNewOwner, EBX);
        enum wasHandled { Yes = 0x44848F, No = 0} Handled = No;

        BuildingExt::ExtData* bldExt = BuildingExt::ExtMap.Find(pBld);

        if(bldExt->ignoreNextEVA) {
                Handled = Yes;
                bldExt->ignoreNextEVA = false;
        }

        return Handled;
}
DEFINE_HOOK ( 458729  ,
BuildingClass_KillOccupiers_AllOccupantsKilled  ,
 
)
{
        GET(BuildingClass *, pBld, ESI);
        BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);

        buildingExtData->evalRaidStatus();

        return 0;
}
DEFINE_HOOK ( 4581CD  ,
BuildingClass_UnloadOccupants_AllOccupantsHaveLeft  ,
 
)
{
    GET(BuildingClass *, pBld, ESI);
    BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);

    buildingExtData->evalRaidStatus();

    return 0;
}
DEFINE_HOOK ( 4586CA  ,
BuildingClass_KillOccupiers_EachOccupierKilled  ,
 
)
{
    GET(BuildingClass *, pBld, ESI);
    GET(int, idxOccupant, EDI);
    // I don't think anyone ever actually tested Assaulter=yes with raiding, putting this here 'cause it's likely needed
        BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);
    buildingExtData->evalRaidStatus();

    return 0;
}
DEFINE_HOOK ( 52297F  ,
InfantryClass_GarrisonBuilding_OccupierEntered  ,
 
)
{
        GET(InfantryClass *, pInf, ESI);
        GET(BuildingClass *, pBld, EBP);
        BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);
        TechnoExt::ExtData* infExtData = TechnoExt::ExtMap.Find(pInf);

        infExtData->GarrisonedIn = pBld;

        // if building and owner are from different players, and the building is not in raided state
        // change the building's owner and mark it as raided
        // but only if that's even necessary - no need to raid urban combat buildings.
        // 27.11.2010 changed to include fix for #1305
        bool differentOwners = (pBld->Owner != pInf->Owner);
        bool ucBuilding = (pBld->Owner->IsNeutral() && (pBld->GetTechnoType()->TechLevel == -1));
        if(differentOwners && !ucBuilding && !buildingExtData->isCurrentlyRaided) {
                buildingExtData->OwnerBeforeRaid = pBld->Owner;
                buildingExtData->isCurrentlyRaided = true;
                pBld->SetOwningHouse(pInf->Owner);
        }
        return 0;
}
DEFINE_HOOK ( 4494D2  ,
BuildingClass_IsSellable  ,
 
)
{
        GET(BuildingClass *, B, ESI);
        BuildingExt::ExtData* curBuildExt = BuildingExt::ExtMap.Find(B);

        enum SellValues {FORCE_SELLABLE, FORCE_UNSELLABLE, DECIDE_NORMALLY} sellTreatment;
        sellTreatment = DECIDE_NORMALLY; // default

        if(curBuildExt->isCurrentlyRaided) {
                sellTreatment = FORCE_UNSELLABLE; // enemy shouldn't be able to sell "borrowed" buildings
        }

        switch(sellTreatment) {
                case FORCE_SELLABLE:
                        return 0x449532;
                case FORCE_UNSELLABLE:
                        return 0x449536;
                case DECIDE_NORMALLY:
                default:
                        return 0;
        }
}
DEFINE_HOOK ( 443414  ,
BuildingClass_ClickedAction  ,
 
)
{
        GET(eAction, Action, EAX);
        GET(BuildingClass *, pThis, ECX);

        GET_STACK(ObjectClass *, pTarget, 0x8);

        if(Action == act_Enter) {
                if(BuildingClass *pTargetBuilding = specific_cast<BuildingClass *>(pTarget)) {
                        CoordStruct XYZ;
                        pTargetBuilding->GetCoords(&XYZ);
                        CellStruct tgt = { short(XYZ.X / 256), short(XYZ.Y / 256) };
                        AresNetEvent::Handlers::RaiseTrenchRedirectClick(pThis, &tgt);
                        R->EAX(1);
                        return 0x44344D;
                }
        }

        return 0;
}
DEFINE_HOOK ( 44725F  ,
BuildingClass_GetCursorOverObject_TargetABuilding  ,
 
)
{
        GET(BuildingClass *, pThis, ESI);
        GET(TechnoClass *, T, EBP);
        // not decided on UI handling yet

        if(T->WhatAmI() == abs_Building) {
                BuildingClass* targetBuilding = specific_cast<BuildingClass *>(T);
                BuildingExt::ExtData* curBuildExt = BuildingExt::ExtMap.Find(pThis);

                if(curBuildExt->canTraverseTo(targetBuilding)) {
                        //show entry cursor, hooked up to traversal logic in Misc/Network.cpp -> AresNetEvent::Handlers::RespondToTrenchRedirectClick
                        R->EAX<eAction>(act_Enter);
                        return 0x447273;
                }
        }

        return 0;
}
DEFINE_HOOK ( 441F2C  ,
BuildingClass_Destroy_KickOutOfRubble  ,
 
)
                                                              {
        GET(BuildingClass*, pBld, ESI);

        // find out whether this destroyed building would turn into rubble
        if(BuildingTypeExt::ExtData *pTData = BuildingTypeExt::ExtMap.Find(pBld->Type)) {
                if(pTData->RubbleDestroyed) {
                        if(BuildingExt::ExtData *pData = BuildingExt::ExtMap.Find(pBld)) {
                                // this is not the rubble, but the old intact building.
                                // since we force the same foundation this is no problem.
                                pData->KickOutOfRubble();
                        }
                }
        }

        return 0;
}
DEFINE_HOOK ( 441F12  ,
BuildingClass_Destroy_RubbleYell  ,
 
)
{
        GET(BuildingClass *, pThis, ESI);
        BuildingExt::ExtData* BuildingAresData = BuildingExt::ExtMap.Find(pThis);
        BuildingTypeExt::ExtData* destrBuildTE = BuildingTypeExt::ExtMap.Find(pThis->Type);

        // If this object has a rubble building set, turn
        if(destrBuildTE->RubbleDestroyed) {
                ++Unsorted::IKnowWhatImDoing;
                BuildingAresData->RubbleYell();
                --Unsorted::IKnowWhatImDoing;
        }

        return 0;
}
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines