1//************************************************************************** 2//** 3//** ## ## ## ## ## #### #### ### ### 4//** ## ## ## ## ## ## ## ## ## ## #### #### 5//** ## ## ## ## ## ## ## ## ## ## ## ## ## ## 6//** ## ## ######## ## ## ## ## ## ## ## ### ## 7//** ### ## ## ### ## ## ## ## ## ## 8//** # ## ## # #### #### ## ## 9//** 10//** $Id: EntityEx.Inventory.vc 4024 2009-06-20 16:11:22Z firebrand_kh $ 11//** 12//** Copyright (C) 1999-2006 Jānis Legzdiņš 13//** 14//** This program is free software; you can redistribute it and/or 15//** modify it under the terms of the GNU General Public License 16//** as published by the Free Software Foundation; either version 2 17//** of the License, or (at your option) any later version. 18//** 19//** This program is distributed in the hope that it will be useful, 20//** but WITHOUT ANY WARRANTY; without even the implied warranty of 21//** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22//** GNU General Public License for more details. 23//** 24//************************************************************************** 25 26//========================================================================== 27// 28// AddInventory 29// 30//========================================================================== 31 32void AddInventory(Inventory Item) 33{ 34 if (Item.Owner) 35 { 36 if (Item.Owner == self) 37 { 38 // Already in the inventory. 39 return; 40 } 41 // Remove from current owner's inventory. 42 EntityEx(Item.Owner).RemoveInventory(Item); 43 } 44 45 // Add it at the top of the inventory. 46 Item.Inventory = Inventory; 47 Inventory = Item; 48 49 // Set itsm's owner 50 Item.Owner = self; 51} 52 53//========================================================================== 54// 55// RemoveInventory 56// 57//========================================================================== 58 59void RemoveInventory(Inventory Item) 60{ 61 // Find previous item or owner itself, if it's the first item. 62 EntityEx Prev = self; 63 while (Prev && Prev.Inventory != Item) 64 { 65 Prev = Prev.Inventory; 66 } 67 68 // Unlink and remove owner. 69 Prev.Inventory = Item.Inventory; 70 Item.DetachedFromOwner(); 71 Item.Owner = none; 72} 73 74//========================================================================== 75// 76// FindInventory 77// 78//========================================================================== 79 80final Inventory FindInventory(class<Inventory> ItemClass) 81{ 82 Inventory Check; 83 84 for (Check = Inventory; Check; Check = Check.Inventory) 85 { 86 if (Check.Class == ItemClass) 87 { 88 return Check; 89 } 90 } 91 return none; 92} 93 94//========================================================================== 95// 96// GiveInventoryType 97// 98//========================================================================== 99 100final Inventory GiveInventoryType(class<Inventory> Type) 101{ 102 Inventory Item = Spawn(Type,,,, false); 103 // This shouldn't count for the item statistics 104 if (Item.bCountItem) 105 { 106 Item.bCountItem = false; 107 Level.TotalItems--; 108 } 109 Item.bDropped = true; 110 if (!Item.TryPickup(self)) 111 { 112 Item.Destroy(); 113 return none; 114 } 115 return Item; 116} 117 118//========================================================================== 119// 120// DestroyAllInventory 121// 122//========================================================================== 123 124final void DestroyAllInventory() 125{ 126 while (Inventory) 127 { 128 Inventory.Destroy(); 129 } 130} 131 132//========================================================================== 133// 134// UseInventory 135// 136//========================================================================== 137 138bool UseInventory(Inventory Item) 139{ 140 // Don't use items if you are dead. 141 if (Health <= 0) 142 { 143 return false; 144 } 145 // Don't use item if don't actually have it. 146 if (Item.Amount <= 0) 147 { 148 return false; 149 } 150 if (!Item.Use(false)) 151 { 152 return false; 153 } 154 // Item was used - remove it from inventory 155 Item.Amount--; 156 if (Item.Amount <= 0 && !Item.bKeepDepleted) 157 { 158 Item.Destroy(); 159 } 160 return true; 161} 162 163//========================================================================== 164// 165// DropInventory 166// 167//========================================================================== 168 169EntityEx DropInventory(Inventory SrcItem) 170{ 171 TVec Dir; 172 173 AngleVector(&Angles, &Dir); 174 Dir.z = 0.0; 175 Dir = Normalise(Dir); 176 Inventory Item = SrcItem.CreateTossable(); 177 if (Item) 178 { 179 Item.SetOrigin2(Origin + vector(0.0, 0.0, 32.0) + 180 Dir * (Radius + 32.0)); 181 Item.Angles.yaw = Angles.yaw; 182 Item.Velocity = Dir * 128.0; 183 } 184 return Item; 185} 186 187//========================================================================== 188// 189// ObtainInventory 190// 191//========================================================================== 192 193void ObtainInventory(EntityEx Other) 194{ 195 // Actor should not have any inventory. 196 if (Inventory) 197 { 198 Error("ObtainInventory called while still having an inventory"); 199 } 200 201 Inventory = Other.Inventory; 202 Other.Inventory = none; 203 Inventory Item; 204 for (Item = Inventory; Item; Item = Item.Inventory) 205 { 206 Item.Owner = self; 207 } 208} 209 210//=========================================================================== 211// 212// ClearInventory 213// 214//=========================================================================== 215 216final void ClearInventory() 217{ 218 Inventory Item = Inventory; 219 while (Item) 220 { 221 Inventory Next = Item.Inventory; 222 if (!Item.bUndroppable) 223 { 224 // IMHO any item that should be kept should not be dropped, 225 // not just ammo. 226 if (Item.bKeepDepleted) 227 { 228 Item.Amount = 0; 229 } 230 else 231 { 232 Item.Destroy(); 233 } 234 } 235 else if (HexenArmor(Item)) 236 { 237 HexenArmor A = HexenArmor(Item); 238 A.Slots[0] = 0.0; 239 A.Slots[1] = 0.0; 240 A.Slots[2] = 0.0; 241 A.Slots[3] = 0.0; 242 } 243 Item = Next; 244 } 245 246 if (bIsPlayer) 247 { 248 PlayerEx(Player).ReadyWeapon = none; 249 PlayerEx(Player).PendingWeapon = none; 250 Player.SetViewState(ps_weapon, none); 251 Player.SetViewState(ps_flash, none); 252 } 253} 254 255//=========================================================================== 256// 257// GiveInventory 258// 259//=========================================================================== 260 261final void GiveInventory(name ItemName, int Amount) 262{ 263 if (Amount <= 0) 264 { 265 return; 266 } 267 if (ItemName == 'armor') 268 { 269 ItemName = 'basicarmor'; 270 } 271 272 // Get class of the item. 273 class EClass = FindClassLowerCase(ItemName); 274 if (!EClass) 275 { 276 print("Unknown item type %n", ItemName); 277 return; 278 } 279 class<Inventory> ItemClass = class<Inventory>(EClass); 280 if (!ItemClass) 281 { 282 print("%n is not an inventory class", ItemName); 283 return; 284 } 285 286 Weapon SavedPendingWeapon = none; 287 bool HadWeapon = true; 288 if (bIsPlayer) 289 { 290 SavedPendingWeapon = PlayerEx(Player).PendingWeapon; 291 HadWeapon = !!PlayerEx(Player).ReadyWeapon; 292 } 293 294 Inventory Item = Spawn(ItemClass,,,, false); 295 // This shouldn't count for the item statistics 296 if (Item.bCountItem) 297 { 298 Item.bCountItem = false; 299 Level.TotalItems--; 300 } 301 if (BasicArmorPickup(Item)) 302 { 303 BasicArmorPickup(Item).SaveAmount *= Amount; 304 } 305 else if (BasicArmorBonus(Item)) 306 { 307 BasicArmorBonus(Item).SaveAmount *= Amount; 308 } 309 else 310 { 311 Item.Amount = Amount; 312 } 313 314 if (!Item.TryPickup(self)) 315 { 316 Item.Destroy(); 317 } 318 // Don't automatically bring up weapon. 319 if (bIsPlayer && HadWeapon) 320 { 321 PlayerEx(Player).PendingWeapon = SavedPendingWeapon; 322 } 323} 324 325//=========================================================================== 326// 327// TakeInventory 328// 329//=========================================================================== 330 331final void TakeInventory(name ItemName, int Amount) 332{ 333 if (Amount <= 0) 334 { 335 return; 336 } 337 if (ItemName == 'armor') 338 { 339 ItemName = 'basicarmor'; 340 } 341 342 // Get class of the item. 343 class<Inventory> ItemClass = class<Inventory>(FindClassLowerCase( 344 ItemName)); 345 if (!ItemClass) 346 { 347 return; 348 } 349 350 Inventory Item = FindInventory(ItemClass); 351 if (!Item) 352 { 353 return; 354 } 355 356 Item.Amount -= Amount; 357 if (Item.Amount <= 0) 358 { 359 if (Item.bKeepDepleted) 360 { 361 Item.Amount = 0; 362 } 363 else 364 { 365 Item.Destroy(); 366 } 367 } 368} 369 370//=========================================================================== 371// 372// CheckInventory 373// 374//=========================================================================== 375 376final int CheckInventory(name ItemName) 377{ 378 if (ItemName == 'armor') 379 { 380 ItemName = 'basicarmor'; 381 } 382 else if (ItemName == 'health') 383 { 384 return Health; 385 } 386 387 class<Inventory> ItemClass = class<Inventory>(FindClassLowerCase( 388 ItemName)); 389 if (ItemClass) 390 { 391 Inventory Item = FindInventory(ItemClass); 392 return Item ? Item.Amount : 0; 393 } 394 return 0; 395} 396 397//=========================================================================== 398// 399// UseInventoryName 400// 401//=========================================================================== 402 403final int UseInventoryName(name ItemName) 404{ 405 class<Inventory> ItemClass = class<Inventory>(FindClassLowerCase( 406 ItemName)); 407 if (ItemClass) 408 { 409 Inventory Item = FindInventory(ItemClass); 410 if (Item) 411 { 412 return UseInventory(Item); 413 } 414 } 415 return 0; 416} 417 418//=========================================================================== 419// 420// GetArmorPoints 421// 422//=========================================================================== 423 424final int GetArmorPoints() 425{ 426 Inventory A = FindInventory(BasicArmor); 427 return A ? A.Amount : 0; 428} 429 430//=========================================================================== 431// 432// CheckNamedWeapon 433// 434//=========================================================================== 435 436final int CheckNamedWeapon(name Name) 437{ 438 if (!bIsPlayer || !PlayerEx(Player).ReadyWeapon) 439 { 440 return false; 441 } 442 return !stricmp(va("%n", Name), va("%n", GetClassName( 443 PlayerEx(Player).ReadyWeapon.Class))); 444} 445 446//=========================================================================== 447// 448// SetNamedWeapon 449// 450//=========================================================================== 451 452final int SetNamedWeapon(name Name) 453{ 454 if (!bIsPlayer) 455 { 456 return false; 457 } 458 459 Weapon Wpn = Weapon(FindInventory(class<Inventory>(FindClassLowerCase( 460 Name)))); 461 if (!Wpn) 462 { 463 return false; 464 } 465 // Check if it's already active. 466 if (PlayerEx(Player).ReadyWeapon == Wpn) 467 { 468 // Make sure player doesn't switch away from it. 469 PlayerEx(Player).PendingWeapon = none; 470 return true; 471 } 472 // Check if weapon has enough ammo. 473 if (!Wpn.CheckAmmo(Weapon::FIRE_Either, false)) 474 { 475 return false; 476 } 477 PlayerEx(Player).PendingWeapon = Wpn; 478 return true; 479} 480 481//=========================================================================== 482// 483// GetAmmoCapacity 484// 485//=========================================================================== 486 487final int GetAmmoCapacity(name Name) 488{ 489 class<Ammo> AmmoType = class<Ammo>(FindClassLowerCase(Name)); 490 if (!AmmoType) 491 { 492 return 0; 493 } 494 // Only direct descendants of Ammo class. 495 if (GetClassParent(AmmoType) != Ammo) 496 { 497 return 0; 498 } 499 // If we have this ammo, return current max amount, otherwise return 500 // default for this ammo type. 501 Inventory Item = FindInventory(AmmoType); 502 if (Item) 503 { 504 return Item.MaxAmount; 505 } 506 else 507 { 508 return AmmoType.default.MaxAmount; 509 } 510} 511 512//=========================================================================== 513// 514// SetAmmoCapacity 515// 516//=========================================================================== 517 518final void SetAmmoCapacity(name Name, int Amount) 519{ 520 class<Ammo> AmmoType = class<Ammo>(FindClassLowerCase(Name)); 521 if (!AmmoType) 522 { 523 return; 524 } 525 // Only direct descendants of Ammo class. 526 if (GetClassParent(AmmoType) != Ammo) 527 { 528 return; 529 } 530 531 // Make sure new ammo capacity is not negative. 532 if (Amount < 0) 533 { 534 Amount = 0; 535 } 536 537 Inventory Item = FindInventory(AmmoType); 538 if (!Item) 539 { 540 Item = GiveInventoryType(AmmoType); 541 Item.Amount = 0; 542 } 543 Item.MaxAmount = Amount; 544 // We also should make sure that the current amount doesn't exceed the 545 // new limit. 546 if (Item.Amount > Item.MaxAmount) 547 { 548 Item.Amount = Item.MaxAmount; 549 } 550} 551