void CAIWeaponAbstract::DefaultReload(CAI* pAI) { if (!m_pWeapon) { return; } if (pAI) { pAI->GetAIWorldState()->SetWSProp( kWSK_WeaponLoaded, pAI->GetHOBJECT(), kWST_bool, true ); } m_eFiringState = kAIFiringState_Reloading; UpdateWeaponAnimation(pAI); if( m_pWeapon->GetAmmoInClip() > 0 ) { return; } m_pWeapon->ReloadClip( false ); // Keep track of reload counts on the blackboard. uint32 nRounds = pAI->GetAIBlackBoard()->GetBBRoundsFired(); pAI->GetAIBlackBoard()->SetBBRoundsFired( nRounds + 1 ); // After a reload we may not have any ammo in our reserves. if (m_pAIWeaponRecord && m_pAIWeaponRecord->bAllowAmmoGeneration) { m_pWeapon->GetArsenal()->AddAmmo( m_pWeapon->GetAmmoRecord(), 999999 ); } }
bool Inventory::SetEquippedSlot(ieWordSigned slotcode, ieWord header) { EquippedHeader = header; //doesn't work if magic slot is used, refresh the magic slot just in case if (HasItemInSlot("",SLOT_MAGIC) && (slotcode!=SLOT_MAGIC-SLOT_MELEE)) { Equipped = SLOT_MAGIC-SLOT_MELEE; UpdateWeaponAnimation(); return false; } //if it is an illegal code, make it fist if ((size_t) (slotcode+SLOT_MELEE)>Slots.size()) { slotcode=IW_NO_EQUIPPED; } //unequipping (fist slot will be used now) if (slotcode == IW_NO_EQUIPPED || !HasItemInSlot("",slotcode+SLOT_MELEE)) { if (Equipped != IW_NO_EQUIPPED) { RemoveSlotEffects( SLOT_MELEE+Equipped); } Equipped = IW_NO_EQUIPPED; //fist slot equipping effects AddSlotEffects(SLOT_FIST); UpdateWeaponAnimation(); return true; } //equipping a weapon, but remove its effects first if (Equipped != IW_NO_EQUIPPED) { RemoveSlotEffects( SLOT_MELEE+Equipped); } Equipped = slotcode; int effects = core->QuerySlotEffects( SLOT_MELEE+Equipped ); if (effects) { CREItem* item = GetSlotItem(SLOT_MELEE+Equipped); item->Flags|=IE_INV_ITEM_EQUIPPED; if (item->Flags & IE_INV_ITEM_CURSED) { item->Flags|=IE_INV_ITEM_UNDROPPABLE; } AddSlotEffects( SLOT_MELEE+Equipped); } UpdateWeaponAnimation(); return true; }
void CAIWeaponAbstract::DefaultAim(CAI* pAI) { if (pAI) { pAI->GetAnimationContext()->SetProp( kAPG_Action, kAP_ACT_Aim ); } UpdateWeaponAnimation(pAI); }
bool CAIWeaponAbstract::DefaultFire(CAI* pAI, const LTVector& vTargetPos, bool bAnimatesReload) { if( !( m_pWeapon && m_pAIWeaponRecord ) ) { return false; } HOBJECT hTarget = pAI->GetAIBlackBoard()->GetBBTargetObject(); // Get our fire position LTVector vFirePos = GetFirePosition(pAI); // Get our firing vector LTVector vDir = vTargetPos - vFirePos; vDir.Normalize(); // Now fire the weapon WeaponFireInfo weaponFireInfo; static uint8 s_nCount = GetRandom( 0, 255 ); s_nCount++; weaponFireInfo.hFiredFrom = pAI->GetHOBJECT(); weaponFireInfo.vPath = vDir; weaponFireInfo.vFirePos = vFirePos; weaponFireInfo.vFlashPos = vFirePos; weaponFireInfo.hTestObj = hTarget; weaponFireInfo.hFiringWeapon = m_pWeapon->GetModelObject(); weaponFireInfo.nSeed = (uint8)GetRandom( 2, 255 ); weaponFireInfo.nPerturbCount = s_nCount; weaponFireInfo.nFireTimestamp = g_pLTServer->GetRealTimeMS( ); weaponFireInfo.bLeftHandWeapon = ( LTStrIEquals( m_szFireSocketName.c_str( ), "LEFTHAND" ) ); if( pAI->GetAIBlackBoard()->GetBBPerfectAccuracy() ) { weaponFireInfo.fPerturb = 0.0f; } else { weaponFireInfo.fPerturb = 1.f; } WeaponState eWeaponState = m_pWeapon->UpdateWeapon( weaponFireInfo, true ); if( eWeaponState == W_FIRED ) { UpdateWeaponAnimation( pAI ); } if( m_pWeapon->GetAmmoInClip() == 0 ) { // Automatically reload if: // 1) The AI has more ammo for this weapon and // 2) Either the AI is flagged to autoreload, or the weapon is flagged to not animation reloads. if( AIWeaponUtils::HasAmmo(pAI, m_pAIWeaponRecord->eAIWeaponType, !AIWEAP_CHECK_HOLSTER) && ( ( pAI->GetAIBlackBoard()->GetBBAutoReload() && m_pAIWeaponRecord->bAllowAutoReload ) || !bAnimatesReload) ) { Reload(pAI); } else { pAI->GetAIWorldState()->SetWSProp( kWSK_WeaponLoaded, pAI->GetHOBJECT(), kWST_bool, false ); } } else { pAI->GetAIWorldState()->SetWSProp( kWSK_WeaponLoaded, pAI->GetHOBJECT(), kWST_bool, true ); } // If the primary weapon is now out of ammo, set the WeaponArmed // worldstate to false. if( pAI->GetAIBlackBoard()->GetBBPrimaryWeaponType() == m_pAIWeaponRecord->eAIWeaponType && !AIWeaponUtils::HasAmmo(pAI, m_pAIWeaponRecord->eAIWeaponType, !AIWEAP_CHECK_HOLSTER)) { pAI->GetAIBlackBoard()->SetBBSelectAction(true); } return true; }
//this is the low level equipping //all checks have been made previously bool Inventory::EquipItem(unsigned int slot) { ITMExtHeader *header; if (!Owner) { //maybe assertion too? return false; } CREItem *item = GetSlotItem(slot); if (!item) { return false; } int weaponslot; // add effects of an item just being equipped to actor's effect queue int effect = core->QuerySlotEffects( slot ); Item *itm = gamedata->GetItem(item->ItemResRef); if (!itm) { printf("Invalid item Equipped: %s Slot: %d\n", item->ItemResRef, slot); return false; } switch (effect) { case SLOT_EFFECT_LEFT: //no idea if the offhand weapon has style, or simply the right //hand style is dominant UpdateShieldAnimation(itm); break; case SLOT_EFFECT_MELEE: //if weapon is ranged, then find quarrel for it and equip that slot -= SLOT_MELEE; weaponslot = slot; EquippedHeader = 0; header = itm->GetExtHeader(EquippedHeader); if (header && header->AttackType == ITEM_AT_BOW) { //find the ranged projectile associated with it. slot = FindRangedProjectile(header->ProjectileQualifier); EquippedHeader = itm->GetWeaponHeaderNumber(true); } else if (header && header->AttackType == ITEM_AT_PROJECTILE) { EquippedHeader = itm->GetWeaponHeaderNumber(true); } else { EquippedHeader = itm->GetWeaponHeaderNumber(false); } header = itm->GetExtHeader(EquippedHeader); if (header) { SetEquippedSlot(slot, EquippedHeader); if (slot != IW_NO_EQUIPPED) { Owner->SetupQuickSlot(ACT_WEAPON1+weaponslot, slot+SLOT_MELEE, EquippedHeader); } effect = 0; // SetEquippedSlot will already call AddSlotEffects UpdateWeaponAnimation(); } break; case SLOT_EFFECT_MISSILE: //Get the ranged header of the projectile (so we theoretically allow shooting of daggers) EquippedHeader = itm->GetWeaponHeaderNumber(true); header = itm->GetExtHeader(EquippedHeader); if (header) { weaponslot = FindTypedRangedWeapon(header->ProjectileQualifier); if (weaponslot != SLOT_FIST) { weaponslot -= SLOT_MELEE; SetEquippedSlot((ieWordSigned) (slot-SLOT_MELEE), EquippedHeader); //It is unsure if we can have multiple equipping headers for bows/arrow //It is unclear which item's header index should go there Owner->SetupQuickSlot(ACT_WEAPON1+weaponslot, slot, 0); } UpdateWeaponAnimation(); } break; case SLOT_EFFECT_HEAD: Owner->SetUsedHelmet(itm->AnimationType); break; case SLOT_EFFECT_ITEM: //adjusting armour level if needed { int l = itm->AnimationType[0]-'1'; if (l>=0 && l<=3) { Owner->SetBase(IE_ARMOR_TYPE, l); } else { UpdateShieldAnimation(itm); } } break; } gamedata->FreeItem(itm, item->ItemResRef, false); if (effect) { if (item->Flags & IE_INV_ITEM_CURSED) { item->Flags|=IE_INV_ITEM_UNDROPPABLE; } AddSlotEffects( slot ); } return true; }
void Inventory::KillSlot(unsigned int index) { if (InventoryType==INVENTORY_HEAP) { Slots.erase(Slots.begin()+index); return; } CREItem *item = Slots[index]; if (!item) { return; } //the used up item vanishes from the quickslot bar if (Owner->InParty) { core->SetEventFlag( EF_ACTION ); } Slots[index] = NULL; int effect = core->QuerySlotEffects( index ); if (!effect) { return; } RemoveSlotEffects( index ); Item *itm = gamedata->GetItem(item->ItemResRef); //this cannot happen, but stuff happens! if (!itm) { return; } ItemExcl &= ~itm->ItemExcl; switch (effect) { case SLOT_EFFECT_LEFT: UpdateShieldAnimation(0); break; case SLOT_EFFECT_MISSILE: //getting a new projectile of the same type if (Equipped + SLOT_MELEE == (int) index) { if (Equipped < 0) { //always get the projectile weapon header (this quiver was equipped) ITMExtHeader *header = itm->GetWeaponHeader(true); Equipped = FindRangedProjectile(header->ProjectileQualifier); if (Equipped!=IW_NO_EQUIPPED) { EquipItem(Equipped+SLOT_MELEE); } else { EquipItem(SLOT_FIST); } } } UpdateWeaponAnimation(); break; case SLOT_EFFECT_MELEE: // reset Equipped if it was the removed item if (Equipped+SLOT_MELEE == (int)index) Equipped = IW_NO_EQUIPPED; else if (Equipped < 0) { //always get the projectile weapon header (this is a bow, because Equipped is negative) ITMExtHeader *header = itm->GetWeaponHeader(true); if (header) { //find the equipped type int type = header->ProjectileQualifier; int weaponslot = FindTypedRangedWeapon(type); CREItem *item2 = Slots[weaponslot]; if (item2) { Item *itm2 = gamedata->GetItem(item2->ItemResRef); if (itm2) { if (type == header->ProjectileQualifier) { Equipped = FindRangedProjectile(header->ProjectileQualifier); if (Equipped!=IW_NO_EQUIPPED) { EquipItem(Equipped+SLOT_MELEE); } else { EquipItem(SLOT_FIST); } } gamedata->FreeItem(itm2, item2->ItemResRef, false); } } } } // reset Equipped if it is a ranged weapon slot // but not magic weapon slot! UpdateWeaponAnimation(); break; case SLOT_EFFECT_HEAD: Owner->SetUsedHelmet(""); break; case SLOT_EFFECT_ITEM: //remove the armor type only if this item is responsible for it if ((ieDword) (itm->AnimationType[0]-'1') == Owner->GetBase(IE_ARMOR_TYPE)) { Owner->SetBase(IE_ARMOR_TYPE, 0); } break; } gamedata->FreeItem(itm, item->ItemResRef, false); }
void Inventory::EquipBestWeapon(int flags) { int i; int damage = -1; ieDword best_slot = SLOT_FIST; ITMExtHeader *header; CREItem *Slot; char AnimationType[2]={0,0}; ieWord MeleeAnimation[3]={100,0,0}; //cannot change equipment when holding magic weapons if (Equipped == SLOT_MAGIC-SLOT_MELEE) { return; } if (flags&EQUIP_RANGED) { for(i=SLOT_RANGED;i<LAST_RANGED;i++) { const Item *itm = GetItemPointer(i, Slot); if (!itm) continue; //best ranged int tmp = itm->GetDamagePotential(true, header); if (tmp>damage) { best_slot = i; damage = tmp; memcpy(AnimationType,itm->AnimationType,sizeof(AnimationType) ); memcpy(MeleeAnimation,header->MeleeAnimation,sizeof(MeleeAnimation) ); } gamedata->FreeItem( itm, Slot->ItemResRef, false ); } //ranged melee weapons like throwing daggers (not bows!) for(i=SLOT_MELEE;i<=LAST_MELEE;i++) { const Item *itm = GetItemPointer(i, Slot); if (!itm) continue; //best ranged int tmp = itm->GetDamagePotential(true, header); if (tmp>damage) { best_slot = i; damage = tmp; memcpy(AnimationType,itm->AnimationType,sizeof(AnimationType) ); memcpy(MeleeAnimation,header->MeleeAnimation,sizeof(MeleeAnimation) ); } gamedata->FreeItem( itm, Slot->ItemResRef, false ); } } if (flags&EQUIP_MELEE) { for(i=SLOT_MELEE;i<=LAST_MELEE;i++) { const Item *itm = GetItemPointer(i, Slot); if (!itm) continue; //the Slot flag is enough for this //though we need animation type/damagepotential anyway if (Slot->Flags&IE_INV_ITEM_BOW) continue; //best melee int tmp = itm->GetDamagePotential(false, header); if (tmp>damage) { best_slot = i; damage = tmp; memcpy(AnimationType,itm->AnimationType,sizeof(AnimationType) ); memcpy(MeleeAnimation,header->MeleeAnimation,sizeof(MeleeAnimation) ); } gamedata->FreeItem( itm, Slot->ItemResRef, false ); } } EquipItem(best_slot); UpdateWeaponAnimation(); }