implemented hostile spell/item flag
[gemrb.git] / gemrb / core / Item.cpp
blob7c561608c825743cdcdab0afb9a3aa3c343752cf
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(Scriptable *self, const Point &pos, 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 //this is not coming from the item header, but from the recharge flags
78 fx->SourceFlags = ext_headers[usage].RechargeFlags;
79 if (fx->Target != FX_TARGET_SELF) {
80 fx->Projectile = pro;
81 fxqueue->AddEffect( fx );
82 } else {
83 Actor *target = (self->Type==ST_ACTOR)?(Actor *) self:NULL;
84 fx->Projectile = 0;
85 fx->PosX=pos.x;
86 fx->PosY=pos.y;
87 if (target) {
88 core->ApplyEffect(fx, target, self);
93 //adding a pulse effect for weapons (PST)
94 //if it is an equipping effect block
95 if ((usage==-1) && (WieldColor!=0xffff)) {
96 if (Flags&IE_ITEM_PULSATING) {
97 Effect *tmp = BuildGlowEffect(WieldColor);
98 if (tmp) {
99 tmp->InventorySlot = invslot;
100 tmp->Projectile=pro;
101 fxqueue->AddEffect( tmp );
102 delete tmp;
106 return fxqueue;
109 /** returns the average damage this weapon would cause */
110 int Item::GetDamagePotential(bool ranged, ITMExtHeader *&header) const
112 header = GetWeaponHeader(ranged);
113 if (header) {
114 return header->DiceThrown*(header->DiceSides+1)/2+header->DamageBonus;
116 return -1;
119 int Item::GetWeaponHeaderNumber(bool ranged) const
121 for(int ehc=0; ehc<ExtHeaderCount; ehc++) {
122 ITMExtHeader *ext_header = GetExtHeader(ehc);
123 if (ext_header->Location!=ITEM_LOC_WEAPON) {
124 continue;
126 unsigned char AType = ext_header->AttackType;
127 if (ranged) {
128 if ((AType!=ITEM_AT_PROJECTILE) && (AType!=ITEM_AT_BOW) ) {
129 continue;
131 } else {
132 if (AType!=ITEM_AT_MELEE) {
133 continue;
136 return ehc;
138 return 0xffff; //invalid extheader number
141 int Item::GetEquipmentHeaderNumber(int cnt) const
143 for(int ehc=0; ehc<ExtHeaderCount; ehc++) {
144 ITMExtHeader *ext_header = GetExtHeader(ehc);
145 if (ext_header->Location!=ITEM_LOC_EQUIPMENT) {
146 continue;
148 if (ext_header->AttackType!=ITEM_AT_MAGIC) {
149 continue;
152 if (cnt) {
153 cnt--;
154 continue;
156 return ehc;
158 return 0xffff; //invalid extheader number
161 ITMExtHeader *Item::GetWeaponHeader(bool ranged) const
163 //start from the beginning
164 return GetExtHeader(GetWeaponHeaderNumber(ranged)) ;
167 int Item::UseCharge(ieWord *Charges, int header, bool expend) const
169 ITMExtHeader *ieh = GetExtHeader(header);
170 if (!ieh) return 0;
171 int type = ieh->ChargeDepletion;
173 int ccount = 0;
174 if ((header>=CHARGE_COUNTERS) || (header<0/*weapon header*/)) {
175 header = 0;
177 ccount=Charges[header];
179 //if the item started from 0 charges, then it isn't depleting
180 if (ieh->Charges==0) {
181 return CHG_NONE;
183 if (expend) {
184 Charges[header] = --ccount;
187 if (ccount>0) {
188 return CHG_NONE;
190 if (type == CHG_NONE) {
191 Charges[header]=0;
193 return type;
196 //returns a projectile loaded with the effect queue
197 Projectile *Item::GetProjectile(Scriptable *self, int header, const Point &target, ieDwordSigned invslot, int miss) const
199 ITMExtHeader *eh = GetExtHeader(header);
200 if (!eh) {
201 return NULL;
203 ieDword idx = eh->ProjectileAnimation;
204 Projectile *pro = core->GetProjectileServer()->GetProjectileByIndex(idx);
205 int usage ;
206 if (header>= 0)
207 usage = header;
208 else
209 usage = GetWeaponHeaderNumber(header==-2);
210 if (!miss) {
211 EffectQueue *fx = GetEffectBlock(self, target, usage, invslot, idx);
212 pro->SetEffects(fx);
214 return pro;
217 //this is the implementation of the weapon glow effect in PST
218 static EffectRef glow_ref ={"Color:PulseRGB",NULL,-1};
219 //this type of colour uses PAL32, a PST specific palette
220 #define PALSIZE 32
221 static Color ActorColor[PALSIZE];
223 Effect *Item::BuildGlowEffect(int gradient) const
225 //palette entry to to RGB conversion
226 core->GetPalette( gradient, PALSIZE, ActorColor );
227 ieDword rgb = (ActorColor[16].r<<16) | (ActorColor[16].g<<8) | ActorColor[16].b;
228 ieDword location = 0;
229 ieDword speed = 128;
230 Effect *fx = EffectQueue::CreateEffect(glow_ref, rgb, location|(speed<<16), FX_DURATION_INSTANT_WHILE_EQUIPPED);
231 return fx;
234 unsigned int Item::GetCastingDistance(int idx) const
236 ITMExtHeader *seh = GetExtHeader(idx);
237 if (!seh) {
238 printMessage("Item", "Cannot retrieve item header!!! ",RED);
239 printf("required header: %d, maximum: %d\n", idx, (int) ExtHeaderCount);
240 return 0;
242 return (unsigned int) seh->Range;