Sort include order.
[gemrb.git] / gemrb / core / Item.cpp
blob4739ae7d825b24e0d53574b9cc2b82180d87e94e
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 // This class represents the .itm (item) files of the engine
22 // Items are all the weapons, armor, carriable quest objects, etc.
24 #include "Item.h"
26 #include "win32def.h"
28 #include "Interface.h"
29 #include "Projectile.h"
30 #include "ProjectileServer.h"
32 ITMExtHeader::ITMExtHeader(void)
34 features = NULL;
37 ITMExtHeader::~ITMExtHeader(void)
39 delete [] features;
42 Item::Item(void)
44 ext_headers = NULL;
45 equipping_features = NULL;
48 Item::~Item(void)
50 //core->FreeITMExt( ext_headers, equipping_features );
51 delete [] ext_headers;
52 delete [] equipping_features;
55 //-1 will return equipping feature block
56 //otherwise returns the n'th feature block
57 EffectQueue *Item::GetEffectBlock(int usage, ieDwordSigned invslot, ieDword pro) const
59 Effect *features;
60 int count;
62 if (usage>=ExtHeaderCount) {
63 return NULL;
65 if (usage>=0) {
66 features = ext_headers[usage].features;
67 count = ext_headers[usage].FeatureCount;
68 } else {
69 features = equipping_features;
70 count = EquippingFeatureCount;
72 EffectQueue *fxqueue = new EffectQueue();
74 for (int i=0;i<count;i++) {
75 Effect *fx = features+i;
76 fx->InventorySlot = invslot;
77 fx->Projectile = pro;
78 fxqueue->AddEffect( fx );
81 //adding a pulse effect for weapons (PST)
82 //if it is an equipping effect block
83 if ((usage==-1) && (WieldColor!=0xffff)) {
84 if (Flags&IE_ITEM_PULSATING) {
85 Effect *tmp = BuildGlowEffect(WieldColor);
86 if (tmp) {
87 tmp->InventorySlot = invslot;
88 tmp->Projectile=pro;
89 fxqueue->AddEffect( tmp );
90 delete tmp;
94 return fxqueue;
97 /** returns the average damage this weapon would cause */
98 int Item::GetDamagePotential(bool ranged, ITMExtHeader *&header) const
100 header = GetWeaponHeader(ranged);
101 if (header) {
102 return header->DiceThrown*(header->DiceSides+1)/2+header->DamageBonus;
104 return -1;
107 int Item::GetWeaponHeaderNumber(bool ranged) const
109 for(int ehc=0; ehc<ExtHeaderCount; ehc++) {
110 ITMExtHeader *ext_header = GetExtHeader(ehc);
111 if (ext_header->Location!=ITEM_LOC_WEAPON) {
112 continue;
114 unsigned char AType = ext_header->AttackType;
115 if (ranged) {
116 if ((AType!=ITEM_AT_PROJECTILE) && (AType!=ITEM_AT_BOW) ) {
117 continue;
119 } else {
120 if (AType!=ITEM_AT_MELEE) {
121 continue;
124 return ehc;
126 return 0xffff; //invalid extheader number
129 int Item::GetEquipmentHeaderNumber(int cnt) const
131 for(int ehc=0; ehc<ExtHeaderCount; ehc++) {
132 ITMExtHeader *ext_header = GetExtHeader(ehc);
133 if (ext_header->Location!=ITEM_LOC_EQUIPMENT) {
134 continue;
136 if (ext_header->AttackType!=ITEM_AT_MAGIC) {
137 continue;
140 if (cnt) {
141 cnt--;
142 continue;
144 return ehc;
146 return 0xffff; //invalid extheader number
149 ITMExtHeader *Item::GetWeaponHeader(bool ranged) const
151 //start from the beginning
152 return GetExtHeader(GetWeaponHeaderNumber(ranged)) ;
155 int Item::UseCharge(ieWord *Charges, int header, bool expend) const
157 ITMExtHeader *ieh = GetExtHeader(header);
158 if (!ieh) return 0;
159 int type = ieh->ChargeDepletion;
161 int ccount = 0;
162 if ((header>=CHARGE_COUNTERS) || (header<0/*weapon header*/)) {
163 header = 0;
165 ccount=Charges[header];
167 //if the item started from 0 charges, then it isn't depleting
168 if (ieh->Charges==0) {
169 return CHG_NONE;
171 if (expend) {
172 Charges[header] = --ccount;
175 if (ccount>0) {
176 return CHG_NONE;
178 if (type == CHG_NONE) {
179 Charges[header]=0;
181 return type;
184 //returns a projectile loaded with the effect queue
185 Projectile *Item::GetProjectile(ieDwordSigned invslot, int header, int miss) const
187 ITMExtHeader *eh = GetExtHeader(header);
188 if (!eh) {
189 return NULL;
191 ieDword idx = eh->ProjectileAnimation;
192 Projectile *pro = core->GetProjectileServer()->GetProjectileByIndex(idx);
193 int usage ;
194 if (header>= 0)
195 usage = header ;
196 else
197 usage = GetWeaponHeaderNumber(header==-2) ;
198 if (!miss) {
199 EffectQueue *fx = GetEffectBlock(usage, invslot, idx);
200 pro->SetEffects(fx);
202 return pro;
205 //this is the implementation of the weapon glow effect in PST
206 static EffectRef glow_ref ={"Color:PulseRGB",NULL,-1};
207 //this type of colour uses PAL32, a PST specific palette
208 #define PALSIZE 32
209 static Color ActorColor[PALSIZE];
211 Effect *Item::BuildGlowEffect(int gradient) const
213 //palette entry to to RGB conversion
214 core->GetPalette( gradient, PALSIZE, ActorColor );
215 ieDword rgb = (ActorColor[16].r<<16) | (ActorColor[16].g<<8) | ActorColor[16].b;
216 ieDword location = 0;
217 ieDword speed = 128;
218 Effect *fx = EffectQueue::CreateEffect(glow_ref, rgb, location|(speed<<16), FX_DURATION_INSTANT_WHILE_EQUIPPED);
219 return fx;
222 unsigned int Item::GetCastingDistance(int idx) const
224 ITMExtHeader *seh = GetExtHeader(idx);
225 if (!seh) {
226 printMessage("Item", "Cannot retrieve item header!!! ",RED);
227 printf("required header: %d, maximum: %d\n", idx, (int) ExtHeaderCount);
228 return 0;
230 return (unsigned int) seh->Range;