~ares-developers/ares/gd03

« back to all changes in this revision

Viewing changes to src/Ext/Building/Hooks.Trenches.cpp

  • Committer: Renegade
  • Date: 2010-05-29 08:12:17 UTC
  • Revision ID: git-v1:0a1bb6321f04d723afe64d1b843dc87b4da783ec
Creating /trunk/src.

git-svn-id: svn://svn.renegadeprojects.com/ares/trunk@622 859b54a9-7a54-0410-aeb3-f8d2f1fa40fd

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "Body.h"
 
2
#include "../BuildingType/Body.h"
 
3
#include "../Techno/Body.h"
 
4
#include "../../Misc/Network.h"
 
5
 
 
6
#include <SpecificStructures.h>
 
7
#include <ScenarioClass.h>
 
8
#include <InfantryClass.h>
 
9
#include <CellClass.h>
 
10
 
 
11
#include <cmath>
 
12
 
 
13
/*      #218 - specific occupiers // comes in 0.2
 
14
        #665 - raidable buildings */
 
15
DEFINE_HOOK(457D58, BuildingClass_CanBeOccupied_SpecificOccupiers, 6)
 
16
{
 
17
        GET(BuildingClass *, pThis, ESI);
 
18
        GET(InfantryClass *, pInf, EDI);
 
19
        BuildingTypeExt::ExtData* pBuildTypeExt = BuildingTypeExt::ExtMap.Find(pThis->Type);
 
20
        bool can_occupy = false;
 
21
 
 
22
        if(pInf->Type->Occupier) {
 
23
                bool isFull = (pThis->GetOccupantCount() == pThis->Type->MaxNumberOccupants);
 
24
                bool isEmpty = (pThis->GetOccupantCount() == 0); // yes, yes, !pThis->GetOccupantCount() - leave it this way for semantics :P
 
25
                bool isIneligible = (pThis->IsRedHP() || pInf->IsMindControlled());
 
26
 
 
27
                if(!isFull && !isIneligible) {
 
28
                        if(pThis->Owner != pInf->Owner) {
 
29
                                /*      The building switches owners after the first occupant enters,
 
30
                                        so this check should not interfere with the player who captured it,
 
31
                                        only prevent others from entering it while it's occupied. (Bug #699) */
 
32
                                can_occupy = (pThis->Owner->IsNeutral() || (pBuildTypeExt->BunkerRaidable && isEmpty));
 
33
                        } else {
 
34
                                can_occupy = true;
 
35
                        }
 
36
                }
 
37
        }
 
38
 
 
39
/*
 
40
// original code replaced by this hook
 
41
        if(pInf->Occupier) {
 
42
                if ( pThis->Owner != pInf->Owner && !pThis->Owner->Country->MultiplayPassive
 
43
                        || pThis->GetOccupantCount() == pThis->BuildingType->MaxNumberOccupants
 
44
                        || pThis->IsRedHP()
 
45
                        || pInf->IsMindControlled() )
 
46
                        return 0;
 
47
        }
 
48
        return 1;
 
49
*/
 
50
 
 
51
        return can_occupy ? 0x457DD5 : 0x457DA3;
 
52
}
 
53
 
 
54
 
 
55
// #664: Advanced Rubble - turning into rubble part
 
56
// moved to before the survivors get unlimboed, per sanity's requirements
 
57
//A_FINE_HOOK(44266B, BuildingClass_ReceiveDamage_AfterPreDeathSequence, 6)
 
58
DEFINE_HOOK(441F12, BuildingClass_Destroy_RubbleYell, 6)
 
59
{
 
60
        GET(BuildingClass *, pThis, ESI);
 
61
        BuildingExt::ExtData* BuildingAresData = BuildingExt::ExtMap.Find(pThis);
 
62
        BuildingTypeExt::ExtData* destrBuildTE = BuildingTypeExt::ExtMap.Find(pThis->Type);
 
63
 
 
64
        if(!pThis->C4Timer.Ignorable()) {
 
65
                // If this object has a rubble building set, turn, otherwise die
 
66
                if(destrBuildTE->RubbleDestroyed) {
 
67
                        BuildingAresData->RubbleYell();
 
68
                } else {
 
69
                        pThis->UnInit();
 
70
                        pThis->AfterDestruction();
 
71
                }
 
72
        }
 
73
 
 
74
        /* original code
 
75
        if(pThis->C4Timer.IsDone()) {
 
76
                pThis->UnInit();
 
77
                pThis->AfterDestruction();
 
78
        }*/
 
79
        return 0;
 
80
}
 
81
 
 
82
// #666: Trench Traversal - check if traversal is possible & cursor display
 
83
DEFINE_HOOK(44725F, BuildingClass_GetCursorOverObject_TargetABuilding, 5)
 
84
{
 
85
        GET(BuildingClass *, pThis, ESI);
 
86
        GET(TechnoClass *, T, EBP);
 
87
        // not decided on UI handling yet
 
88
 
 
89
        if(T->WhatAmI() == abs_Building) {
 
90
                BuildingClass* targetBuilding = specific_cast<BuildingClass *>(T);
 
91
                BuildingExt::ExtData* curBuildExt = BuildingExt::ExtMap.Find(pThis);
 
92
 
 
93
                if(curBuildExt->canTraverseTo(targetBuilding)) {
 
94
                        //show entry cursor, hooked up to traversal logic in Misc/Network.cpp -> AresNetEvent::Handlers::RespondToTrenchRedirectClick
 
95
                        R->EAX<eAction>(act_Enter);
 
96
                        return 0x447273;
 
97
                }
 
98
        }
 
99
 
 
100
        return 0;
 
101
}
 
102
 
 
103
DEFINE_HOOK(443414, BuildingClass_ClickedMission, 6)
 
104
{
 
105
        GET(eAction, Action, EAX);
 
106
        GET(BuildingClass *, pThis, ECX);
 
107
 
 
108
        GET_STACK(ObjectClass *, pTarget, 0x8);
 
109
 
 
110
        if(Action == act_Enter) {
 
111
                if(BuildingClass *pTargetBuilding = specific_cast<BuildingClass *>(pTarget)) {
 
112
                        CoordStruct XYZ;
 
113
                        pTargetBuilding->GetCoords(&XYZ);
 
114
                        CellStruct tgt = { short(XYZ.X / 256), short(XYZ.Y / 256) };
 
115
                        AresNetEvent::Handlers::RaiseTrenchRedirectClick(pThis, &tgt);
 
116
                        R->EAX(1);
 
117
                        return 0x44344D;
 
118
                }
 
119
        }
 
120
 
 
121
        return 0;
 
122
}
 
123
 
 
124
// #665: Raidable Buildings - prevent raided buildings from being sold while raided
 
125
DEFINE_HOOK(4494D2, BuildingClass_IsSellable, 6)
 
126
{
 
127
        GET(BuildingClass *, B, ESI);
 
128
        BuildingExt::ExtData* curBuildExt = BuildingExt::ExtMap.Find(B);
 
129
 
 
130
        enum SellValues {FORCE_SELLABLE, FORCE_UNSELLABLE, DECIDE_NORMALLY} sellTreatment;
 
131
        sellTreatment = DECIDE_NORMALLY; // default
 
132
 
 
133
        if(curBuildExt->isCurrentlyRaided) {
 
134
                sellTreatment = FORCE_UNSELLABLE; // enemy shouldn't be able to sell "borrowed" buildings
 
135
        }
 
136
 
 
137
        switch(sellTreatment) {
 
138
                case FORCE_SELLABLE:
 
139
                        return 0x449532;
 
140
                case FORCE_UNSELLABLE:
 
141
                        return 0x449536;
 
142
                case DECIDE_NORMALLY:
 
143
                default:
 
144
                        return 0;
 
145
        }
 
146
}
 
147
 
 
148
/* Requested in issue #695
 
149
        Instructions from D:
 
150
        Flow:
 
151
        Occupier is Remove()'d from the map,
 
152
        added to the Occupants list,
 
153
        <-- hook happens here
 
154
        ThreatToCell is updated,
 
155
        "EVA_StructureGarrisoned" is played if applicable.
 
156
*/
 
157
DEFINE_HOOK(52297F, InfantryClass_GarrisonBuilding_OccupierEntered, 5)
 
158
{
 
159
        GET(InfantryClass *, pInf, ESI);
 
160
        GET(BuildingClass *, pBld, EBP);
 
161
        BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);
 
162
        TechnoExt::ExtData* infExtData = TechnoExt::ExtMap.Find(pInf);
 
163
 
 
164
        infExtData->GarrisonedIn = pBld;
 
165
 
 
166
        // if building and owner are from different players, and the building is not in raided state
 
167
        // change the building's owner and mark it as raided
 
168
        // but only if that's even necessary - no need to raid neutral houses.
 
169
        if((pBld->Owner != pInf->Owner) && !pBld->Owner->IsNeutral() && !buildingExtData->isCurrentlyRaided) {
 
170
                buildingExtData->OwnerBeforeRaid = pBld->Owner;
 
171
                buildingExtData->isCurrentlyRaided = true;
 
172
                pBld->SetOwningHouse(pInf->Owner);
 
173
        }
 
174
        return 0;
 
175
}
 
176
 
 
177
/* Requested in issue #694
 
178
        D: The first hook fires each time one of the occupants is ejected through the Deploy function -
 
179
        the game doesn't have a builtin way to remove a single occupant, only all of them, so this is rigged inside that.*/
 
180
// This is CURRENTLY UNUSED - look at Misc/Network.cpp -> AresNetEvent::Handlers::RespondToTrenchRedirectClick
 
181
/*A_FINE_HOOK(4580A9, BuildingClass_UnloadOccupants_EachOccupantLeaves, 6)
 
182
{
 
183
        GET(BuildingClass *, pBld, ESI);
 
184
        GET(int, idxOccupant, EBP);
 
185
 
 
186
        TechnoExt::ExtData* infExtData = TechnoExt::ExtMap.Find(pBld->Occupants[idxOccupant]);
 
187
        infExtData->GarrisonedIn = NULL;
 
188
 
 
189
    / *
 
190
    - get current rally point target; if there is none, exit trench
 
191
    - check if target cell has a building
 
192
                - if so, check if it's the same building
 
193
                        - if so, do nothing
 
194
                        - if not, check building with canTraverseTo
 
195
                                - if true, doTraverseTo
 
196
                                - if false, do nothing
 
197
                - if not, exit trench
 
198
    * /
 
199
 
 
200
    if(0/ * spawned in a different building * /) {
 
201
        return 0x45819D;
 
202
    }
 
203
    // do the normal kickout thing
 
204
    return 0;
 
205
}*/
 
206
 
 
207
/* Requested in issue #694
 
208
        D: The second hook fires each time one of the occupants is killed (Assaulter). Note that it doesn't catch the damage forwarding fatal hit.
 
209
*/
 
210
DEFINE_HOOK(4586CA, BuildingClass_KillOccupiers_EachOccupierKilled, 6)
 
211
{
 
212
    GET(BuildingClass *, pBld, ESI);
 
213
    GET(int, idxOccupant, EDI);
 
214
    // I don't think anyone ever actually tested Assaulter=yes with raiding, putting this here 'cause it's likely needed
 
215
        BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);
 
216
    buildingExtData->evalRaidStatus();
 
217
 
 
218
    return 0;
 
219
}
 
220
 
 
221
/* Requested in issue #694
 
222
        D: The third hook fires after all the occupants have been ejected (by the first hook).
 
223
*/
 
224
DEFINE_HOOK(4581CD, BuildingClass_UnloadOccupants_AllOccupantsHaveLeft, 6)
 
225
{
 
226
    GET(BuildingClass *, pBld, ESI);
 
227
    BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);
 
228
 
 
229
    buildingExtData->evalRaidStatus();
 
230
 
 
231
    return 0;
 
232
}
 
233
 
 
234
/* Requested in issue #694
 
235
        D: The fourth hook fires after all the occupants have been killed by the second hook.
 
236
*/
 
237
DEFINE_HOOK(458729, BuildingClass_KillOccupiers_AllOccupantsKilled, 6)
 
238
{
 
239
        GET(BuildingClass *, pBld, ESI);
 
240
        BuildingExt::ExtData* buildingExtData = BuildingExt::ExtMap.Find(pBld);
 
241
 
 
242
        buildingExtData->evalRaidStatus();
 
243
 
 
244
        return 0;
 
245
}
 
246
 
 
247
/*
 
248
// #666: Trench Traversal - check if traversal is possible & traverse, eject or do nothing, depending on the result
 
249
// This is CURRENTLY UNUSED - look at Misc/Network.cpp -> AresNetEvent::Handlers::RespondToTrenchRedirectClick
 
250
A_FINE_HOOK(457DF5, BuildingClass_UnloadOccupants_AboutToStartUnloading, 6)
 
251
{
 
252
        GET(BuildingClass *, currentBuilding, ESI);
 
253
        /*CellClass* rallyPoint =; // wherever the rally point points to
 
254
        if(BuildingClass* targetBuilding = rallyPoint->GetBuilding()) {
 
255
                BuildingExt::ExtData* currentBuildingExt = BuildingExt::ExtMap.Find(currentBuilding);
 
256
                if(currentBuildingExt->canTraverseTo(targetBuilding)) {
 
257
                        currentBuildingExt->doTraverseTo(targetBuilding); // also calls evalRaidStatus()
 
258
                } else {
 
259
                        // see if we can find a way to abort eviction here
 
260
                }
 
261
        }
 
262
 
 
263
 
 
264
        return 0;
 
265
}
 
266
*/
 
267
 
 
268
/*      #698 - "Building captured" EVA announcement "bug"
 
269
 
 
270
 
 
271
        <DCoder> if you want the original handling (TechBuildingLost, BuildingCaptured, etc) to take place, return No,
 
272
        otherwise perform your own code and return Yes
 
273
        <Renegade> at what place in the chain is that executed?
 
274
        <DCoder> in the middle of where the building changes ownership from old player to new
 
275
*/
 
276
DEFINE_HOOK(448401, BuildingClass_ChangeOwnership_TrenchEVA, 6)
 
277
{
 
278
        GET(BuildingClass *, pBld, ESI);
 
279
        GET(HouseClass *, pNewOwner, EBX);
 
280
        enum wasHandled { Yes = 0x44848F, No = 0} Handled = No;
 
281
 
 
282
        BuildingExt::ExtData* bldExt = BuildingExt::ExtMap.Find(pBld);
 
283
 
 
284
        if(bldExt->ignoreNextEVA) {
 
285
                Handled = Yes;
 
286
                bldExt->ignoreNextEVA = false;
 
287
        }
 
288
 
 
289
        return Handled;
 
290
}