~ares-developers/ares/gd03

« back to all changes in this revision

Viewing changes to src/Ext/Building/Hooks.Prism.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 <BulletClass.h>
 
4
#include <LaserDrawClass.h>
 
5
 
 
6
DEFINE_HOOK(44B2FE, BuildingClass_Mi_Attack_IsPrism, 6)
 
7
{
 
8
        GET(BuildingClass *, B, ESI);
 
9
        GET(int, idxWeapon, EBP); //which weapon was chosen to attack the target with
 
10
        R->EAX<BuildingTypeClass *>(B->Type);
 
11
 
 
12
        enum { IsPrism = 0x44B310, IsNotPrism = 0x44B630, IsCustomPrism = 0x44B6D6};
 
13
 
 
14
        BuildingTypeClass *pMasterType = B->Type;
 
15
        BuildingTypeExt::ExtData *pMasterTypeData = BuildingTypeExt::ExtMap.Find(pMasterType);
 
16
 
 
17
        if (pMasterTypeData->PrismForwarding.Enabled == BuildingTypeExt::cPrismForwarding::YES
 
18
                || pMasterTypeData->PrismForwarding.Enabled == BuildingTypeExt::cPrismForwarding::ATTACK) {
 
19
 
 
20
                if (B->PrismStage == pcs_Idle) {
 
21
                        B->PrismStage = pcs_Master;
 
22
                        B->DelayBeforeFiring = B->Type->DelayedFireDelay;
 
23
                        B->PrismTargetCoords.X = 0;
 
24
                        B->PrismTargetCoords.Y = B->PrismTargetCoords.Z = 0;
 
25
                        B->DestroyNthAnim(BuildingAnimSlot::Active);
 
26
                        B->PlayNthAnim(BuildingAnimSlot::Special);
 
27
 
 
28
                        int LongestChain = 0;
 
29
 
 
30
                        //set up slaves
 
31
                        int NetworkSize = 0;
 
32
                        int stage = 0;
 
33
 
 
34
                        //when it reaches zero we can't acquire any more slaves
 
35
                        while (BuildingTypeExt::cPrismForwarding::AcquireSlaves_MultiStage(B, B, stage++, 0, &NetworkSize, &LongestChain) != 0) {}
 
36
 
 
37
                        //now we have all the towers we know the longest chain, and can set all the towers' charge delays
 
38
                        BuildingTypeExt::cPrismForwarding::SetChargeDelay(B, LongestChain);
 
39
 
 
40
                } else if (B->PrismStage == pcs_Slave) {
 
41
                        Debug::Log("PrismForwarding: Converting Slave to Master\n");
 
42
                        //a slave tower is changing into a master tower at the last second
 
43
                        B->PrismStage = pcs_Master;
 
44
                        BuildingExt::ExtData *pMasterData = BuildingExt::ExtMap.Find(B);
 
45
                        pMasterData->PrismForwarding.SupportTarget = NULL;
 
46
 
 
47
                }
 
48
 
 
49
                return IsCustomPrism; //always custom, the new code is a complete rewrite of the old code
 
50
 
 
51
        }
 
52
 
 
53
        return IsNotPrism;
 
54
}
 
55
 
 
56
DEFINE_HOOK(447FAE, BuildingClass_GetObjectActivityState, 6)
 
57
{
 
58
        GET(BuildingClass *, B, ESI);
 
59
        enum { BusyCharging = 0x447FB8, NotBusyCharging = 0x447FC3};
 
60
 
 
61
        if(B->DelayBeforeFiring > 0) {
 
62
                //if this is a slave prism tower, then it might still be able to become a master tower at this time
 
63
                BuildingTypeClass *pType = B->Type;
 
64
                BuildingTypeExt::ExtData *pTypeData = BuildingTypeExt::ExtMap.Find(pType);
 
65
                if (pTypeData->PrismForwarding.Enabled == BuildingTypeExt::cPrismForwarding::YES
 
66
                                || pTypeData->PrismForwarding.Enabled == BuildingTypeExt::cPrismForwarding::ATTACK) {
 
67
                        //is a prism tower
 
68
                        if (B->PrismStage == pcs_Slave && pTypeData->PrismForwarding.BreakSupport) {
 
69
                                return NotBusyCharging;
 
70
                        }
 
71
                }
 
72
                return BusyCharging;
 
73
        }
 
74
        return NotBusyCharging;
 
75
}
 
76
 
 
77
//NB: PrismTargetCoords is not just a coord struct, it's a union whose first dword is the used weapon index and two others are undefined...
 
78
DEFINE_HOOK(4503F0, BuildingClass_Update_Prism, 9)
 
79
{
 
80
        GET(BuildingClass *, pThis, ECX);
 
81
        if(int PrismStage = pThis->PrismStage) {
 
82
                BuildingExt::ExtData *pData = BuildingExt::ExtMap.Find(pThis);
 
83
                if (pData->PrismForwarding.PrismChargeDelay <= 0) {
 
84
                        --pThis->DelayBeforeFiring;
 
85
                        if(pThis->DelayBeforeFiring <= 0) {
 
86
                                if(PrismStage == pcs_Slave) {
 
87
                                        if (BuildingClass *pTarget = pData->PrismForwarding.SupportTarget) {
 
88
                                                BuildingExt::ExtData *pTargetData = BuildingExt::ExtMap.Find(pTarget);
 
89
                                                BuildingTypeClass *pType = pThis->Type;
 
90
                                                BuildingTypeExt::ExtData *pTypeData = BuildingTypeExt::ExtMap.Find(pType);
 
91
                                                Debug::Log("[PrismForwarding] Slave firing. SM=%d MR=%lf\n",
 
92
                                                        pTypeData->PrismForwarding.SupportModifier.Get(), pData->PrismForwarding.ModifierReserve);
 
93
                                                pTargetData->PrismForwarding.ModifierReserve +=
 
94
                                                        (pTypeData->PrismForwarding.SupportModifier.Get() + pData->PrismForwarding.ModifierReserve);
 
95
                                                pTargetData->PrismForwarding.DamageReserve +=
 
96
                                                        (pTypeData->PrismForwarding.DamageAdd.Get()  + pData->PrismForwarding.DamageReserve);
 
97
                                                pThis->FireLaser(pThis->PrismTargetCoords);
 
98
 
 
99
                                        }
 
100
                                }
 
101
                                if(PrismStage == pcs_Master) {
 
102
                                        if(ObjectClass *Target = pThis->Target) {
 
103
                                                if(pThis->GetFireError(Target, pThis->PrismTargetCoords.X, true) == FireError::OK) {
 
104
                                                        if(BulletClass *LaserBeam = pThis->Fire(Target, pThis->PrismTargetCoords.X)) {
 
105
                                                                BuildingTypeClass *pType = pThis->Type;
 
106
                                                                BuildingTypeExt::ExtData *pTypeData = BuildingTypeExt::ExtMap.Find(pType);
 
107
                                                                LaserBeam->DamageMultiplier = ((pData->PrismForwarding.ModifierReserve + 100) * 256) / 100; //apparently this is divided by 256 elsewhere
 
108
                                                                LaserBeam->Health += pTypeData->PrismForwarding.DamageAdd.Get()  + pData->PrismForwarding.DamageReserve;
 
109
                                                        }
 
110
                                                }
 
111
                                        }
 
112
                                }
 
113
                                //This tower's job is done. Go idle.
 
114
                                pData->PrismForwarding.ModifierReserve = 0.0;
 
115
                                pData->PrismForwarding.DamageReserve = 0;
 
116
                                pData->PrismForwarding.Senders.Clear();
 
117
                                pThis->SupportingPrisms = 0; //Ares doesn't actually use this, but maintaining it anyway (as direct feeds only)
 
118
                                pData->PrismForwarding.SupportTarget = NULL;
 
119
                                pThis->PrismStage = pcs_Idle;
 
120
                        }
 
121
                } else {
 
122
                        //still in delayed charge so not actually charging yet
 
123
                        --pData->PrismForwarding.PrismChargeDelay;
 
124
                        pThis->DestroyNthAnim(BuildingAnimSlot::Active);
 
125
                        pThis->PlayNthAnim(BuildingAnimSlot::Special);
 
126
                }
 
127
        }
 
128
        return 0x4504E2;
 
129
}
 
130
 
 
131
DEFINE_HOOK(44ABD0, BuildingClass_FireLaser, 5)
 
132
{
 
133
        GET(BuildingClass *, B, ECX);
 
134
        LEA_STACK(CoordStruct *, pTargetXYZ, 0x4);
 
135
 
 
136
        BuildingTypeClass *pType = B->Type;
 
137
        BuildingTypeExt::ExtData *pTypeData = BuildingTypeExt::ExtMap.Find(pType);
 
138
 
 
139
        CoordStruct SourceXYZ, Base = {0, 0, 0};
 
140
        B->GetFLH(&SourceXYZ, 0, Base);
 
141
 
 
142
        ColorStruct blank(0, 0, 0);
 
143
 
 
144
        LaserDrawClass * LaserBeam;
 
145
        GAME_ALLOC(LaserDrawClass, LaserBeam, SourceXYZ, *pTargetXYZ,
 
146
                B->Owner->LaserColor, blank, blank, pTypeData->PrismForwarding.SupportDuration);
 
147
 
 
148
        if(LaserBeam) {
 
149
                LaserBeam->IsHouseColor = true;
 
150
                LaserBeam->field_1C = 3;
 
151
        }
 
152
 
 
153
        B->SupportingPrisms = 0;
 
154
        B->ReloadTimer.Start(pTypeData->PrismForwarding.SupportDelay);
 
155
 
 
156
        return 0x44ACE2;
 
157
}
 
158
 
 
159
//these are all for cleaning up when a prism tower becomes unavailable
 
160
DEFINE_HOOK(4424EF, PrismForward_BuildingDestroyed, 6)
 
161
{
 
162
        GET(BuildingClass *, B, ESI);
 
163
        BuildingTypeExt::cPrismForwarding::RemoveSlave(B, true);
 
164
        return 0;
 
165
}
 
166
 
 
167
DEFINE_HOOK(447113, PrismForward_BuildingSold, 6)
 
168
{
 
169
        GET(BuildingClass *, B, ESI);
 
170
        BuildingTypeExt::cPrismForwarding::RemoveSlave(B, true);
 
171
        return 0;
 
172
}
 
173
 
 
174
DEFINE_HOOK(448277, PrismForward_BuildingChangeOwner, 5)
 
175
{
 
176
        GET(BuildingClass *, B, ESI);
 
177
        GET_STACK(HouseClass *, newOwner, 0x5C);
 
178
        
 
179
        HouseClass * oldOwner = B->Owner;
 
180
 
 
181
        if (newOwner != oldOwner) {
 
182
                BuildingTypeClass *pType = B->Type;
 
183
                BuildingTypeExt::ExtData *pTypeData = BuildingTypeExt::ExtMap.Find(pType);
 
184
 
 
185
                if (pTypeData->PrismForwarding.ToAllies) {
 
186
                        BuildingClass *LastTarget = B;
 
187
                        BuildingClass *FirstTarget = NULL;
 
188
                        while (LastTarget) {
 
189
                                BuildingExt::ExtData *pData = BuildingExt::ExtMap.Find(LastTarget);
 
190
                                BuildingClass *NextTarget = pData->PrismForwarding.SupportTarget;
 
191
                                if (!FirstTarget) {
 
192
                                        FirstTarget = NextTarget;
 
193
                                }
 
194
                                if (!NextTarget) {
 
195
                                        //LastTarget is now the master (firing) tower
 
196
                                        if (newOwner->IsAlliedWith(LastTarget->Owner) && newOwner->IsAlliedWith(FirstTarget->Owner)) {
 
197
                                                //alliances check out so this slave tower can keep on charging.
 
198
                                                return 0;
 
199
                                        }
 
200
                                }
 
201
                                LastTarget = NextTarget;
 
202
                        }
 
203
                }
 
204
                //if we reach this point then the alliance checks have failed
 
205
                BuildingTypeExt::cPrismForwarding::RemoveSlave(B, false);
 
206
                
 
207
        }
 
208
 
 
209
        return 0;
 
210
}