Devilution
Diablo devolved - magic behind the 1996 computer game
spells.cpp
Go to the documentation of this file.
1 #include "all.h"
2 
4 
5 int GetManaAmount(int id, int sn)
6 {
7  int ma; // mana amount
8 
9  // mana adjust
10  int adj = 0;
11 
12  // spell level
13  int sl = plr[id]._pSplLvl[sn] + plr[id]._pISplLvlAdd - 1;
14 
15  if (sl < 0) {
16  sl = 0;
17  }
18 
19  if (sn == SPL_FIREBOLT) {
20  adj >>= 1;
21  } else if (sn == SPL_RESURRECT && sl > 0) {
22  adj = sl * (spelldata[SPL_RESURRECT].sManaCost / 8);
23  } else if (sl > 0) {
24  adj = sl * spelldata[sn].sManaAdj;
25  }
26 
27  if (sn == SPL_HEAL || sn == SPL_HEALOTHER) {
28  ma = (spelldata[SPL_HEAL].sManaCost + 2 * plr[id]._pLevel - adj);
29  } else if (spelldata[sn].sManaCost == 255) {
30  ma = ((BYTE)plr[id]._pMaxManaBase - adj);
31  } else {
32  ma = (spelldata[sn].sManaCost - adj);
33  }
34 
35  if (ma < 0)
36  ma = 0;
37  ma <<= 6;
38 
39  if (plr[id]._pClass == PC_ROGUE) {
40  ma -= ma >> 2;
41  }
42 
43  if (spelldata[sn].sMinMana > ma >> 6) {
44  ma = spelldata[sn].sMinMana << 6;
45  }
46 
47  return ma * (100 - plr[id]._pISplCost) / 100;
48 }
49 
50 void UseMana(int id, int sn)
51 {
52  int ma; // mana cost
53 
54  if (id == myplr) {
55  switch (plr[id]._pSplType) {
56  case RSPLTYPE_SKILL:
57  case RSPLTYPE_INVALID:
58  break;
59  case RSPLTYPE_SCROLL:
60  RemoveScroll(id);
61  break;
62  case RSPLTYPE_CHARGES:
63  UseStaffCharge(id);
64  break;
65  case RSPLTYPE_SPELL:
66 #ifdef _DEBUG
67  if (!debug_mode_key_inverted_v) {
68 #endif
69  ma = GetManaAmount(id, sn);
70  plr[id]._pMana -= ma;
71  plr[id]._pManaBase -= ma;
72  drawmanaflag = TRUE;
73 #ifdef _DEBUG
74  }
75 #endif
76  break;
77  }
78  }
79 }
80 
81 BOOL CheckSpell(int id, int sn, char st, BOOL manaonly)
82 {
83  BOOL result;
84 
85 #ifdef _DEBUG
86  if (debug_mode_key_inverted_v)
87  return TRUE;
88 #endif
89 
90  result = TRUE;
91  if (!manaonly && pcurs != CURSOR_HAND) {
92  result = FALSE;
93  } else {
94  if (st != RSPLTYPE_SKILL) {
95  if (GetSpellLevel(id, sn) <= 0) {
96  result = FALSE;
97  } else {
98  result = plr[id]._pMana >= GetManaAmount(id, sn);
99  }
100  }
101  }
102 
103  return result;
104 }
105 
106 void CastSpell(int id, int spl, int sx, int sy, int dx, int dy, int caster, int spllvl)
107 {
108  int i;
109  int dir; // missile direction
110 
111  switch (caster) {
112  case 1:
113  dir = monster[id]._mdir;
114  break;
115  case 0:
116  // caster must be 0 already in this case, but oh well,
117  // it's needed to generate the right code
118  caster = 0;
119  dir = plr[id]._pdir;
120 
121  if (spl == SPL_FIREWALL) {
122  dir = plr[id]._pVar3;
123  }
124  break;
125  }
126 
127  for (i = 0; spelldata[spl].sMissiles[i] != MIS_ARROW && i < 3; i++) {
128  AddMissile(sx, sy, dx, dy, dir, spelldata[spl].sMissiles[i], caster, id, 0, spllvl);
129  }
130 
131  if (spelldata[spl].sMissiles[0] == MIS_TOWN) {
132  UseMana(id, SPL_TOWN);
133  }
134  if (spelldata[spl].sMissiles[0] == MIS_CBOLT) {
135  UseMana(id, SPL_CBOLT);
136 
137  for (i = (spllvl >> 1) + 3; i > 0; i--) {
138  AddMissile(sx, sy, dx, dy, dir, MIS_CBOLT, caster, id, 0, spllvl);
139  }
140  }
141 }
142 
143 static void PlacePlayer(int pnum)
144 {
145  int nx, ny, max, min, x, y;
146  DWORD i;
147  BOOL done;
148 
149  if (plr[pnum].plrlevel == currlevel) {
150  for (i = 0; i < 8; i++) {
151  nx = plr[pnum].WorldX + plrxoff2[i];
152  ny = plr[pnum].WorldY + plryoff2[i];
153 
154  if (PosOkPlayer(pnum, nx, ny)) {
155  break;
156  }
157  }
158 
159  if (!PosOkPlayer(pnum, nx, ny)) {
160  done = FALSE;
161 
162  for (max = 1, min = -1; min > -50 && !done; max++, min--) {
163  for (y = min; y <= max && !done; y++) {
164  ny = plr[pnum].WorldY + y;
165 
166  for (x = min; x <= max && !done; x++) {
167  nx = plr[pnum].WorldX + x;
168 
169  if (PosOkPlayer(pnum, nx, ny)) {
170  done = TRUE;
171  }
172  }
173  }
174  }
175  }
176 
177  plr[pnum].WorldX = nx;
178  plr[pnum].WorldY = ny;
179 
180  dPlayer[nx][ny] = pnum + 1;
181 
182  if (pnum == myplr) {
183  ViewX = nx;
184  ViewY = ny;
185  }
186  }
187 }
188 
193 void DoResurrect(int pnum, int rid)
194 {
195  int hp;
196 
197  if ((char)rid != -1) {
198  AddMissile(plr[rid].WorldX, plr[rid].WorldY, plr[rid].WorldX, plr[rid].WorldY, 0, MIS_RESURRECTBEAM, 0, pnum, 0, 0);
199  }
200 
201  if (pnum == myplr) {
203  }
204 
205  if ((char)rid != -1 && plr[rid]._pHitPoints == 0) {
206  if (rid == myplr) {
207  deathflag = FALSE;
208  gamemenu_off();
209  drawhpflag = TRUE;
210  drawmanaflag = TRUE;
211  }
212 
213  ClrPlrPath(rid);
214  plr[rid].destAction = ACTION_NONE;
215  plr[rid]._pInvincible = FALSE;
216  PlacePlayer(rid);
217 
218  hp = 640;
219  if (plr[rid]._pMaxHPBase < 640) {
220  hp = plr[rid]._pMaxHPBase;
221  }
222  SetPlayerHitPoints(rid, hp);
223 
224  plr[rid]._pHPBase = plr[rid]._pHitPoints + (plr[rid]._pMaxHPBase - plr[rid]._pMaxHP);
225  plr[rid]._pMana = 0;
226  plr[rid]._pManaBase = plr[rid]._pMana + (plr[rid]._pMaxManaBase - plr[rid]._pMaxMana);
227 
228  CalcPlrInv(rid, TRUE);
229 
230  if (plr[rid].plrlevel == currlevel) {
231  StartStand(rid, plr[rid]._pdir);
232  } else {
233  plr[rid]._pmode = PM_STAND;
234  }
235  }
236 }
237 
238 void DoHealOther(int pnum, int rid)
239 {
240  int i, j, hp;
241 
242  if (pnum == myplr) {
244  }
245 
246  if ((char)rid != -1 && (plr[rid]._pHitPoints >> 6) > 0) {
247  hp = (random_(57, 10) + 1) << 6;
248 
249  for (i = 0; i < plr[pnum]._pLevel; i++) {
250  hp += (random_(57, 4) + 1) << 6;
251  }
252 
253  for (j = 0; j < GetSpellLevel(pnum, SPL_HEALOTHER); ++j) {
254  hp += (random_(57, 6) + 1) << 6;
255  }
256 
257  if (plr[pnum]._pClass == PC_WARRIOR) {
258  hp <<= 1;
259  }
260 
261  if (plr[pnum]._pClass == PC_ROGUE) {
262  hp += hp >> 1;
263  }
264 
265  plr[rid]._pHitPoints += hp;
266 
267  if (plr[rid]._pHitPoints > plr[rid]._pMaxHP) {
268  plr[rid]._pHitPoints = plr[rid]._pMaxHP;
269  }
270 
271  plr[rid]._pHPBase += hp;
272 
273  if (plr[rid]._pHPBase > plr[rid]._pMaxHPBase) {
274  plr[rid]._pHPBase = plr[rid]._pMaxHPBase;
275  }
276 
277  drawhpflag = TRUE;
278  }
279 }
280 
PlayerStruct::_pISplCost
char _pISplCost
Definition: structs.h:330
PlayerStruct::_pManaBase
int _pManaBase
Definition: structs.h:261
PosOkPlayer
BOOL PosOkPlayer(int pnum, int x, int y)
Definition: player.cpp:3475
SetPlayerHitPoints
void SetPlayerHitPoints(int pnum, int val)
Definition: player.cpp:3971
currlevel
BYTE currlevel
Definition: gendung.cpp:40
PlayerStruct::_pMaxHP
int _pMaxHP
Definition: structs.h:259
SPL_FIREBOLT
@ SPL_FIREBOLT
Definition: enums.h:2131
PlayerStruct::_pMana
int _pMana
Definition: structs.h:263
SPL_RESURRECT
@ SPL_RESURRECT
Definition: enums.h:2162
SPL_HEALOTHER
@ SPL_HEALOTHER
Definition: enums.h:2164
RSPLTYPE_CHARGES
@ RSPLTYPE_CHARGES
Definition: enums.h:2061
PlayerStruct::destAction
int destAction
Definition: structs.h:182
SpellData::sManaCost
unsigned char sManaCost
Definition: structs.h:1017
PlayerStruct::_pMaxHPBase
int _pMaxHPBase
Definition: structs.h:257
MIS_CBOLT
@ MIS_CBOLT
Definition: enums.h:1246
PlayerStruct::_pVar3
int _pVar3
Definition: structs.h:279
PlayerStruct::WorldX
int WorldX
Definition: structs.h:188
PlayerStruct::_pHPBase
int _pHPBase
Definition: structs.h:256
CURSOR_HAND
@ CURSOR_HAND
Definition: enums.h:2067
DoHealOther
void DoHealOther(int pnum, int rid)
Definition: spells.cpp:238
gamemenu_off
void gamemenu_off()
Definition: gamemenu.cpp:85
MIS_TOWN
@ MIS_TOWN
Definition: enums.h:1204
SPL_TOWN
@ SPL_TOWN
Definition: enums.h:2137
SPL_FIREWALL
@ SPL_FIREWALL
Definition: enums.h:2136
ViewX
int ViewX
Definition: gendung.cpp:73
PlayerStruct::_pSplLvl
char _pSplLvl[64]
Definition: structs.h:225
RSPLTYPE_SPELL
@ RSPLTYPE_SPELL
Definition: enums.h:2059
ClrPlrPath
void ClrPlrPath(int pnum)
Definition: player.cpp:3466
PlayerStruct::_pdir
int _pdir
Definition: structs.h:202
PlayerStruct::_pLevel
char _pLevel
Definition: structs.h:266
CalcPlrInv
void CalcPlrInv(int p, BOOL Loadgfx)
Definition: items.cpp:764
all.h
ViewY
int ViewY
Definition: gendung.cpp:74
spelldata
DEVILUTION_BEGIN_NAMESPACE SpellData spelldata[]
Data related to each spell ID.
Definition: spelldat.cpp:6
AddMissile
int AddMissile(int sx, int sy, int dx, int dy, int midir, int mitype, char micaster, int id, int midam, int spllvl)
Definition: missiles.cpp:2455
PlayerStruct::_pMaxMana
int _pMaxMana
Definition: structs.h:264
RemoveScroll
void RemoveScroll(int pnum)
Definition: inv.cpp:2008
MonsterStruct::_mdir
int _mdir
Definition: structs.h:558
DEVILUTION_END_NAMESPACE
#define DEVILUTION_END_NAMESPACE
Definition: types.h:10
PlacePlayer
static void PlacePlayer(int pnum)
Definition: spells.cpp:143
monster
MonsterStruct monster[MAXMONSTERS]
Definition: monster.cpp:19
PlayerStruct::_pISplLvlAdd
char _pISplLvlAdd
Definition: structs.h:329
RSPLTYPE_SCROLL
@ RSPLTYPE_SCROLL
Definition: enums.h:2060
PlayerStruct::_pInvincible
BOOLEAN _pInvincible
Definition: structs.h:234
RSPLTYPE_INVALID
@ RSPLTYPE_INVALID
Definition: enums.h:2062
StartStand
void StartStand(int pnum, int dir)
Definition: player.cpp:1056
MIS_RESURRECTBEAM
@ MIS_RESURRECTBEAM
Definition: enums.h:1256
SPL_CBOLT
@ SPL_CBOLT
Definition: enums.h:2160
RSPLTYPE_SKILL
@ RSPLTYPE_SKILL
Definition: enums.h:2058
NewCursor
void NewCursor(int i)
Definition: cursor.cpp:107
plrxoff2
int plrxoff2[9]
Definition: player.cpp:34
SPL_HEAL
@ SPL_HEAL
Definition: enums.h:2132
PlayerStruct::_pMaxManaBase
int _pMaxManaBase
Definition: structs.h:262
GetSpellLevel
int GetSpellLevel(int id, int sn)
Definition: missiles.cpp:249
CheckSpell
BOOL CheckSpell(int id, int sn, char st, BOOL manaonly)
Definition: spells.cpp:81
DoResurrect
void DoResurrect(int pnum, int rid)
Definition: spells.cpp:193
SpellData::sMissiles
unsigned char sMissiles[3]
Definition: structs.h:1027
SpellData::sMinMana
unsigned char sMinMana
Definition: structs.h:1029
GetManaAmount
DEVILUTION_BEGIN_NAMESPACE int GetManaAmount(int id, int sn)
Definition: spells.cpp:5
SpellData::sManaAdj
unsigned char sManaAdj
Definition: structs.h:1028
myplr
int myplr
Definition: player.cpp:9
random_
int random_(BYTE idx, int v)
Main RNG function.
Definition: engine.cpp:752
PlayerStruct::_pHitPoints
int _pHitPoints
Definition: structs.h:258
UseMana
void UseMana(int id, int sn)
Definition: spells.cpp:50
PC_WARRIOR
@ PC_WARRIOR
Definition: enums.h:2706
drawmanaflag
BOOL drawmanaflag
Definition: control.cpp:24
PC_ROGUE
@ PC_ROGUE
Definition: enums.h:2707
pcurs
int pcurs
Definition: cursor.cpp:27
DEVILUTION_BEGIN_NAMESPACE
Definition: sha.cpp:10
CastSpell
void CastSpell(int id, int spl, int sx, int sy, int dx, int dy, int caster, int spllvl)
Definition: spells.cpp:106
MIS_ARROW
@ MIS_ARROW
Definition: enums.h:1194
ACTION_NONE
@ ACTION_NONE
Definition: enums.h:2906
dPlayer
char dPlayer[MAXDUNX][MAXDUNY]
Definition: gendung.cpp:49
drawhpflag
BOOL drawhpflag
Definition: control.cpp:14
PlayerStruct::_pmode
int _pmode
Definition: structs.h:179
PlayerStruct::WorldY
int WorldY
Definition: structs.h:189
PM_STAND
@ PM_STAND
Definition: enums.h:2043
plryoff2
int plryoff2[9]
Definition: player.cpp:35
plr
PlayerStruct plr[MAX_PLRS]
Definition: player.cpp:10
UseStaffCharge
void UseStaffCharge(int pnum)
Definition: inv.cpp:2059
deathflag
BOOL deathflag
Definition: player.cpp:13