tsangk69 Posted May 27, 2017 Share Posted May 27, 2017 Need Help Reviewing some script, can't detect error: Error [mod0000_mergedfiles]game\player\playerwitcher.ws(10844): Unexpected end of file found after '{' at line 11 Error [mod0000_mergedfiles]game\player\r4player.ws(14519): Unexpected end of file found after '{' at line 2 [spoiler]Playwitcher: /***********************************************************************/ /** © 2015 CD PROJEKT S.A. All rights reserved. /** THE WITCHER® is a trademark of CD PROJEKT S. A. /** The Witcher game is based on the prose of Andrzej Sapkowski. /***********************************************************************/ statemachine class W3PlayerWitcher extends CR4Player { private saved var craftingSchematics : array; private saved var alchemyRecipes : array; // -= WMK:modAQOOM =- public saved var wmkMapMenuData : WmkMapMenuData; public var wmkMapMenu : WmkMapMenuEx; // -= WMK:modAQOOM =- private saved var booksRead : array; private var fastAttackCounter, heavyAttackCounter : int; private var isInFrenzy : bool; private var hasRecentlyCountered : bool; private saved var cannotUseUndyingSkill : bool; protected saved var amountOfSetPiecesEquipped : array; public var canSwitchFocusModeTarget : bool; protected var switchFocusModeTargetAllowed : bool; default canSwitchFocusModeTarget = true; default switchFocusModeTargetAllowed = true; private editable var signs : array< SWitcherSign >; private saved var equippedSign : ESignType; private var currentlyCastSign : ESignType; default currentlyCastSign = ST_None; private var signOwner : W3SignOwnerPlayer; private var usedQuenInCombat : bool; public var yrdenEntities : array; public saved var m_quenReappliedCount : int; default equippedSign = ST_Aard; default m_quenReappliedCount = 1; private var bDispalyHeavyAttackIndicator : bool; private var bDisplayHeavyAttackFirstLevelTimer : bool; public var specialAttackHeavyAllowed : bool; default bIsCombatActionAllowed = true; default bDispalyHeavyAttackIndicator = false; default bDisplayHeavyAttackFirstLevelTimer = true; default explorationInputContext = 'Exploration'; default combatInputContext = 'Combat'; default combatFistsInputContext = 'Combat'; private saved var companionNPCTag : name; private saved var companionNPCTag2 : name; private saved var companionNPCIconPath : string; private saved var companionNPCIconPath2 : string; private saved var itemSlots : array; private var remainingBombThrowDelaySlot1 : float; private var remainingBombThrowDelaySlot2 : float; private var previouslyUsedBolt : SItemUniqueId; private saved var questMarkedSelectedQuickslotItems : array< SSelectedQuickslotItem >; default isThrowingItem = false; default remainingBombThrowDelaySlot1 = 0.f; default remainingBombThrowDelaySlot2 = 0.f; private saved var tempLearnedSignSkills : array; public saved var autoLevel : bool; protected saved var skillBonusPotionEffect : CBaseGameplayEffect; public saved var levelManager : W3LevelManager; saved var reputationManager : W3Reputation; private editable var medallionEntity : CEntityTemplate; private var medallionController : W3MedallionController; public var bShowRadialMenu : bool; private var _HoldBeforeOpenRadialMenuTime : float; default _HoldBeforeOpenRadialMenuTime = 0.5f; public var MappinToHighlight : array; protected saved var horseManagerHandle : EntityHandle; private var isInitialized : bool; private var timeForPerk21 : float; default isInitialized = false; private var invUpdateTransaction : bool; default invUpdateTransaction = false; event OnSpawned( spawnData : SEntitySpawnData ) { var i : int; var items : array; var items2 : array; var horseTemplate : CEntityTemplate; var horseManager : W3HorseManager; AddAnimEventCallback( 'ActionBlend', 'OnAnimEvent_ActionBlend' ); AddAnimEventCallback('cast_begin', 'OnAnimEvent_Sign'); AddAnimEventCallback('cast_throw', 'OnAnimEvent_Sign'); AddAnimEventCallback('cast_end', 'OnAnimEvent_Sign'); AddAnimEventCallback('cast_friendly_begin', 'OnAnimEvent_Sign'); AddAnimEventCallback('cast_friendly_throw', 'OnAnimEvent_Sign'); AddAnimEventCallback('axii_ready', 'OnAnimEvent_Sign'); AddAnimEventCallback('axii_alternate_ready', 'OnAnimEvent_Sign'); AddAnimEventCallback('yrden_draw_ready', 'OnAnimEvent_Sign'); AddAnimEventCallback( 'ProjectileThrow', 'OnAnimEvent_Throwable' ); AddAnimEventCallback( 'OnWeaponReload', 'OnAnimEvent_Throwable' ); AddAnimEventCallback( 'ProjectileAttach', 'OnAnimEvent_Throwable' ); AddAnimEventCallback( 'Mutation11AnimEnd', 'OnAnimEvent_Mutation11AnimEnd' ); AddAnimEventCallback( 'Mutation11ShockWave', 'OnAnimEvent_Mutation11ShockWave' ); amountOfSetPiecesEquipped.Resize( EnumGetMax( 'EItemSetType' ) + 1 ); runewordInfusionType = ST_None; inv = GetInventory(); signOwner = new W3SignOwnerPlayer in this; signOwner.Init( this ); itemSlots.Resize( EnumGetMax('EEquipmentSlots')+1 ); if(!spawnData.restored) { levelManager = new W3LevelManager in this; levelManager.Initialize(); inv.GetAllItems(items); for(i=0; i { if(inv.IsItemMounted(items[i]) && ( !inv.IsItemBody(items[i]) || inv.GetItemCategory(items[i]) == 'hair' ) ) EquipItem(items[i]); } AddAlchemyRecipe('Recipe for Swallow 1',true,true); AddAlchemyRecipe('Recipe for Cat 1',true,true); AddAlchemyRecipe('Recipe for White Honey 1',true,true); AddAlchemyRecipe('Recipe for Samum 1',true,true); AddAlchemyRecipe('Recipe for Grapeshot 1',true,true); AddAlchemyRecipe('Recipe for Specter Oil 1',true,true); AddAlchemyRecipe('Recipe for Necrophage Oil 1',true,true); AddAlchemyRecipe('Recipe for Alcohest 1',true,true); } else { AddTimer('DelayedOnItemMount', 0.1, true); CheckHairItem(); } AddStartingSchematics(); super.OnSpawned( spawnData ); AddAlchemyRecipe('Recipe for Mutagen red',true,true); AddAlchemyRecipe('Recipe for Mutagen green',true,true); AddAlchemyRecipe('Recipe for Mutagen blue',true,true); AddAlchemyRecipe('Recipe for Greater mutagen red',true,true); AddAlchemyRecipe('Recipe for Greater mutagen green',true,true); AddAlchemyRecipe('Recipe for Greater mutagen blue',true,true); AddCraftingSchematic('Starting Armor Upgrade schematic 1',true,true); if( inputHandler ) { inputHandler.BlockAllActions( 'being_ciri', false ); } SetBehaviorVariable( 'test_ciri_replacer', 0.0f); if(!spawnData.restored) { abilityManager.GainStat(BCS_Toxicity, 0); } levelManager.PostInit(this, spawnData.restored, true); SetBIsCombatActionAllowed( true ); SetBIsInputAllowed( true, 'OnSpawned' ); if ( !reputationManager ) { reputationManager = new W3Reputation in this; reputationManager.Initialize(); } theSound.SoundParameter( "focus_aim", 1.0f, 1.0f ); theSound.SoundParameter( "focus_distance", 0.0f, 1.0f ); currentlyCastSign = ST_None; if(!spawnData.restored) { horseTemplate = (CEntityTemplate)LoadResource("horse_manager"); horseManager = (W3HorseManager)theGame.CreateEntity(horseTemplate, GetWorldPosition(),,,,,PM_Persist); horseManager.CreateAttachment(this); horseManager.OnCreated(); EntityHandleSet( horseManagerHandle, horseManager ); } else { AddTimer('DelayedHorseUpdate', 0.01, true); } RemoveAbility('Ciri_CombatRegen'); RemoveAbility('Ciri_Rage'); RemoveAbility('CiriBlink'); RemoveAbility('CiriCharge'); RemoveAbility('Ciri_Q205'); RemoveAbility('Ciri_Q305'); RemoveAbility('Ciri_Q403'); RemoveAbility('Ciri_Q111'); RemoveAbility('Ciri_Q501'); RemoveAbility('SkillCiri'); if(spawnData.restored) { RestoreQuen(savedQuenHealth, savedQuenDuration); } else { savedQuenHealth = 0.f; savedQuenDuration = 0.f; } if(spawnData.restored) { ApplyPatchFixes(); } else { FactsAdd( "new_game_started_in_1_20" ); } if ( FactsQuerySum("NewGamePlus") > 0 ) { NewGamePlusAdjustDLC1TemerianSet(inv); NewGamePlusAdjustDLC5NilfgardianSet(inv); NewGamePlusAdjustDLC10WolfSet(inv); NewGamePlusAdjustDLC14SkelligeSet(inv); if(horseManager) { NewGamePlusAdjustDLC1TemerianSet(horseManager.GetInventoryComponent()); NewGamePlusAdjustDLC5NilfgardianSet(horseManager.GetInventoryComponent()); NewGamePlusAdjustDLC10WolfSet(horseManager.GetInventoryComponent()); NewGamePlusAdjustDLC14SkelligeSet(horseManager.GetInventoryComponent()); } } ResumeStaminaRegen('WhirlSkill'); if(HasAbility('Runeword 4 _Stats', true)) StartVitalityRegen(); if(HasAbility('sword_s19')) { RemoveTemporarySkills(); } inv = thePlayer.GetInventory(); inv.GetAllItems(items); // Leveling Starting Armor for(i=0; i { if( thePlayer.inv.ItemHasTag(items[i], 'ArmorMod') || thePlayer.inv.ItemHasTag(items[i], 'dlcModArmor') ) // Only ArmorMod items in your inventory { thePlayer.GetInventory().GetItemLevel(items[i]); // Makes sure the Item Level is Re-Set on level up thePlayer.GetInventory().GetItemArmorTotal(items[i], true); // Makes sure the Item Armor is Re-Set on level up } // End } HACK_UnequipWolfLiver(); if( HasBuff( EET_GryphonSetBonusYrden ) ) { RemoveBuff( EET_GryphonSetBonusYrden, false, "GryphonSetBonusYrden" ); } if( spawnData.restored ) { UpdateEncumbrance(); RemoveBuff( EET_Mutation11Immortal ); } isInitialized = true; } private function HACK_UnequipWolfLiver() { var itemName1, itemName2, itemName3, itemName4 : name; var item1, item2, item3, item4 : SItemUniqueId; GetItemEquippedOnSlot( EES_Potion1, item1 ); GetItemEquippedOnSlot( EES_Potion2, item2 ); GetItemEquippedOnSlot( EES_Potion3, item3 ); GetItemEquippedOnSlot( EES_Potion4, item4 ); if ( inv.IsIdValid( item1 ) ) itemName1 = inv.GetItemName( item1 ); if ( inv.IsIdValid( item2 ) ) itemName2 = inv.GetItemName( item2 ); if ( inv.IsIdValid( item3 ) ) itemName3 = inv.GetItemName( item3 ); if ( inv.IsIdValid( item4 ) ) itemName4 = inv.GetItemName( item4 ); if ( itemName1 == 'Wolf liver' || itemName3 == 'Wolf liver' ) { if ( inv.IsIdValid( item1 ) ) UnequipItem( item1 ); if ( inv.IsIdValid( item3 ) ) UnequipItem( item3 ); } else if ( itemName2 == 'Wolf liver' || itemName4 == 'Wolf liver' ) { if ( inv.IsIdValid( item2 ) ) UnequipItem( item2 ); if ( inv.IsIdValid( item4 ) ) UnequipItem( item4 ); } } timer function DelayedHorseUpdate( dt : float, id : int ) { var man : W3HorseManager; man = GetHorseManager(); if(man) { if ( man.ApplyHorseUpdateOnSpawn() ) { UpdateEncumbrance(); RemoveTimer( 'DelayedHorseUpdate' ); } } } event OnAbilityAdded( abilityName : name) { super.OnAbilityAdded(abilityName); if( HasAbility('Runeword 4 _Stats', true) ) { StartVitalityRegen(); } if ( abilityName == 'Runeword 8 _Stats' && GetStat(BCS_Focus, true) >= GetStatMax(BCS_Focus) && !HasBuff(EET_Runeword8) ) { AddEffectDefault(EET_Runeword8, this, "equipped item"); } } private final function AddStartingSchematics() { AddCraftingSchematic('Starting Armor Upgrade schematic 1', true,true); AddCraftingSchematic('Thread schematic', true, true); AddCraftingSchematic('String schematic', true, true); AddCraftingSchematic('Linen schematic', true, true); AddCraftingSchematic('Silk schematic', true, true); AddCraftingSchematic('Resin schematic', true, true); AddCraftingSchematic('Blasting powder schematic', true, true); AddCraftingSchematic('Haft schematic', true, true); AddCraftingSchematic('Hardened timber schematic', true, true); AddCraftingSchematic('Leather squares schematic', true, true); AddCraftingSchematic('Leather schematic', true, true); AddCraftingSchematic('Hardened leather schematic', true, true); AddCraftingSchematic('Draconide leather schematic', true, true); AddCraftingSchematic('Iron ingot schematic', true, true); AddCraftingSchematic('Steel ingot schematic', true, true); AddCraftingSchematic('Steel ingot schematic 1', true, true); AddCraftingSchematic('Steel plate schematic', true, true); AddCraftingSchematic('Dark iron ingot schematic', true, true); AddCraftingSchematic('Dark iron plate schematic', true, true); AddCraftingSchematic('Dark steel ingot schematic', true, true); AddCraftingSchematic('Dark steel ingot schematic 1', true, true); AddCraftingSchematic('Dark steel plate schematic', true, true); AddCraftingSchematic('Silver ore schematic', true, true); AddCraftingSchematic('Silver ingot schematic', true, true); AddCraftingSchematic('Silver ingot schematic 1', true, true); AddCraftingSchematic('Silver plate schematic', true, true); AddCraftingSchematic('Meteorite ingot schematic', true, true); AddCraftingSchematic('Meteorite silver ingot schematic', true, true); AddCraftingSchematic('Meteorite silver plate schematic', true, true); AddCraftingSchematic('Glowing ingot schematic', true, true); AddCraftingSchematic('Dwimeryte ore schematic', true, true); AddCraftingSchematic('Dwimeryte ingot schematic', true, true); AddCraftingSchematic('Dwimeryte ingot schematic 1', true, true); AddCraftingSchematic('Dwimeryte plate schematic', true, true); AddCraftingSchematic('Infused dust schematic', true, true); AddCraftingSchematic('Infused shard schematic', true, true); AddCraftingSchematic('Infused crystal schematic', true, true); if ( theGame.GetDLCManager().IsEP2Available() ) { AddCraftingSchematic('Draconide infused leather schematic', true, true); AddCraftingSchematic('Nickel ore schematic', true, true); AddCraftingSchematic('Cupronickel ore schematic', true, true); AddCraftingSchematic('Copper ore schematic', true, true); AddCraftingSchematic('Copper ingot schematic', true, true); AddCraftingSchematic('Copper plate schematic', true, true); AddCraftingSchematic('Green gold ore schematic', true, true); AddCraftingSchematic('Green gold ore schematic 1', true, true); AddCraftingSchematic('Green gold ingot schematic', true, true); AddCraftingSchematic('Green gold plate schematic', true, true); AddCraftingSchematic('Orichalcum ore schematic', true, true); AddCraftingSchematic('Orichalcum ore schematic 1', true, true); AddCraftingSchematic('Orichalcum ingot schematic', true, true); AddCraftingSchematic('Orichalcum plate schematic', true, true); AddCraftingSchematic('Dwimeryte enriched ore schematic', true, true); AddCraftingSchematic('Dwimeryte enriched ingot schematic', true, true); AddCraftingSchematic('Dwimeryte enriched plate schematic', true, true); } } private final function ApplyPatchFixes() { var cnt, transmutationCount, mutagenCount, i : int; var transmutationAbility, itemName : name; var pam : W3PlayerAbilityManager; var slotId : int; var offset : float; var buffs : array; var mutagen : W3Mutagen_Effect; var skill : SSimpleSkill; var spentSkillPoints, swordSkillPointsSpent, alchemySkillPointsSpent, perkSkillPointsSpent, pointsToAdd : int; var mutagens : array< W3Mutagen_Effect >; if(FactsQuerySum("ClearingPotionPassiveBonusFix") < 1) { pam = (W3PlayerAbilityManager)abilityManager; cnt = GetAbilityCount('sword_adrenalinegain') - pam.GetPathPointsSpent(ESP_Sword); if(cnt > 0) RemoveAbilityMultiple('sword_adrenalinegain', cnt); cnt = GetAbilityCount('magic_staminaregen') - pam.GetPathPointsSpent(ESP_Signs); if(cnt > 0) RemoveAbilityMultiple('magic_staminaregen', cnt); cnt = GetAbilityCount('alchemy_potionduration') - pam.GetPathPointsSpent(ESP_Alchemy); if(cnt > 0) RemoveAbilityMultiple('alchemy_potionduration', cnt); FactsAdd("ClearingPotionPassiveBonusFix"); } if(FactsQuerySum("DimeritiumSynergyFix") < 1) { slotId = GetSkillSlotID(S_Alchemy_s19); if(slotId != -1) UnequipSkill(S_Alchemy_s19); RemoveAbilityAll('greater_mutagen_color_green_synergy_bonus'); RemoveAbilityAll('mutagen_color_green_synergy_bonus'); RemoveAbilityAll('mutagen_color_lesser_green_synergy_bonus'); RemoveAbilityAll('greater_mutagen_color_blue_synergy_bonus'); RemoveAbilityAll('mutagen_color_blue_synergy_bonus'); RemoveAbilityAll('mutagen_color_lesser_blue_synergy_bonus'); RemoveAbilityAll('greater_mutagen_color_red_synergy_bonus'); RemoveAbilityAll('mutagen_color_red_synergy_bonus'); RemoveAbilityAll('mutagen_color_lesser_red_synergy_bonus'); if(slotId != -1) EquipSkill(S_Alchemy_s19, slotId); FactsAdd("DimeritiumSynergyFix"); } if(FactsQuerySum("DontShowRecipePinTut") < 1) { FactsAdd( "DontShowRecipePinTut" ); TutorialScript('alchemyRecipePin', ''); TutorialScript('craftingRecipePin', ''); } if(FactsQuerySum("LevelReqPotGiven") < 1) { FactsAdd("LevelReqPotGiven"); inv.AddAnItem('Wolf Hour', 1, false, false, true); } if(!HasBuff(EET_AutoStaminaRegen)) { AddEffectDefault(EET_AutoStaminaRegen, this, 'autobuff', false); } buffs = GetBuffs(); offset = 0; mutagenCount = 0; for(i=0; i { mutagen = (W3Mutagen_Effect)buffs[i]; if(mutagen) { offset += mutagen.GetToxicityOffset(); mutagenCount += 1; } } if(offset != (GetStat(BCS_Toxicity) - GetStat(BCS_Toxicity, true))) SetToxicityOffset(offset); mutagenCount *= GetSkillLevel(S_Alchemy_s13); transmutationAbility = GetSkillAbilityName(S_Alchemy_s13); transmutationCount = GetAbilityCount(transmutationAbility); if(mutagenCount < transmutationCount) { RemoveAbilityMultiple(transmutationAbility, transmutationCount - mutagenCount); } else if(mutagenCount > transmutationCount) { AddAbilityMultiple(transmutationAbility, mutagenCount - transmutationCount); } if(theGame.GetDLCManager().IsEP1Available()) { theGame.GetJournalManager().ActivateEntryByScriptTag('TutorialJournalEnchanting', JS_Active); } if(HasAbility('sword_s19') && FactsQuerySum("Patch_Sword_s19") < 1) { pam = (W3PlayerAbilityManager)abilityManager; skill.level = 0; for(i = S_Magic_s01; i <= S_Magic_s20; i+=1) { skill.skillType = i; pam.RemoveTemporarySkill(skill); } spentSkillPoints = levelManager.GetPointsUsed(ESkillPoint); swordSkillPointsSpent = pam.GetPathPointsSpent(ESP_Sword); alchemySkillPointsSpent = pam.GetPathPointsSpent(ESP_Alchemy); perkSkillPointsSpent = pam.GetPathPointsSpent(ESP_Perks); pointsToAdd = spentSkillPoints - swordSkillPointsSpent - alchemySkillPointsSpent - perkSkillPointsSpent; if(pointsToAdd > 0) levelManager.UnspendPoints(ESkillPoint, pointsToAdd); RemoveAbilityAll('sword_s19'); FactsAdd("Patch_Sword_s19"); } if( HasAbility( 'sword_s19' ) ) { RemoveAbilityAll( 'sword_s19' ); } if(FactsQuerySum("Patch_Armor_Type_Glyphwords") < 1) { pam = (W3PlayerAbilityManager)abilityManager; pam.SetPerkArmorBonus( S_Perk_05, this ); pam.SetPerkArmorBonus( S_Perk_06, this ); pam.SetPerkArmorBonus( S_Perk_07, this ); FactsAdd("Patch_Armor_Type_Glyphwords"); } else if( FactsQuerySum("154999") < 1 ) { pam = (W3PlayerAbilityManager)abilityManager; pam.SetPerkArmorBonus( S_Perk_05, this ); pam.SetPerkArmorBonus( S_Perk_06, this ); pam.SetPerkArmorBonus( S_Perk_07, this ); FactsAdd("154999"); } if( FactsQuerySum( "Patch_Decoction_Buff_Icons" ) < 1 ) { mutagens = GetMutagenBuffs(); for( i=0; i { itemName = DecoctionEffectTypeToItemName( mutagens[i].GetEffectType() ); mutagens[i].OverrideIcon( itemName ); } FactsAdd( "Patch_Decoction_Buff_Icons" ); } } public final function RestoreQuen( quenHealth : float, quenDuration : float, optional alternate : bool ) : bool { var restoredQuen : W3QuenEntity; if(quenHealth > 0.f && quenDuration >= 3.f) { restoredQuen = (W3QuenEntity)theGame.CreateEntity( signs[ST_Quen].template, GetWorldPosition(), GetWorldRotation() ); restoredQuen.Init( signOwner, signs[ST_Quen].entity, true ); if( alternate ) { restoredQuen.SetAlternateCast( S_Magic_s04 ); } restoredQuen.OnStarted(); restoredQuen.OnThrowing(); if( !alternate ) { restoredQuen.OnEnded(); } restoredQuen.SetDataFromRestore(quenHealth, quenDuration); return true; } return false; } public function IsInitialized() : bool { return isInitialized; } private function NewGamePlusInitialize() { var questItems : array; var horseManager : W3HorseManager; var horseInventory : CInventoryComponent; var i, missingLevels, expDiff : int; super.NewGamePlusInitialize(); horseManager = (W3HorseManager)EntityHandleGet(horseManagerHandle); if(horseManager) horseInventory = horseManager.GetInventoryComponent(); theGame.params.SetNewGamePlusLevel(GetLevel()); if (theGame.GetDLCManager().IsDLCAvailable('ep1')) missingLevels = theGame.params.NEW_GAME_PLUS_EP1_MIN_LEVEL - GetLevel(); else missingLevels = theGame.params.NEW_GAME_PLUS_MIN_LEVEL - GetLevel(); for(i=0; i { expDiff = levelManager.GetTotalExpForNextLevel() - levelManager.GetPointsTotal(EExperiencePoint); expDiff = CeilF( ((float)expDiff) / 2 ); AddPoints(EExperiencePoint, expDiff, false); } inv.RemoveItemByTag('Quest', -1); horseInventory.RemoveItemByTag('Quest', -1); questItems = theGame.GetDefinitionsManager().GetItemsWithTag('Quest'); for(i=0; i { inv.RemoveItemByName(questItems[i], -1); horseInventory.RemoveItemByName(questItems[i], -1); } inv.RemoveItemByName('mq1002_artifact_3', -1); horseInventory.RemoveItemByName('mq1002_artifact_3', -1); inv.RemoveItemByTag('NotTransferableToNGP', -1); horseInventory.RemoveItemByTag('NotTransferableToNGP', -1); inv.RemoveItemByTag('NoticeBoardNote', -1); horseInventory.RemoveItemByTag('NoticeBoardNote', -1); RemoveAllNonAutoBuffs(); RemoveAlchemyRecipe('Recipe for Trial Potion Kit'); RemoveAlchemyRecipe('Recipe for Pops Antidote'); RemoveAlchemyRecipe('Recipe for Czart Lure'); RemoveAlchemyRecipe('q603_diarrhea_potion_recipe'); inv.RemoveItemByTag('Trophy', -1); horseInventory.RemoveItemByTag('Trophy', -1); inv.RemoveItemByCategory('usable', -1); horseInventory.RemoveItemByCategory('usable', -1); RemoveAbility('StaminaTutorialProlog'); RemoveAbility('TutorialStaminaRegenHack'); RemoveAbility('area_novigrad'); RemoveAbility('NoRegenEffect'); RemoveAbility('HeavySwimmingStaminaDrain'); RemoveAbility('AirBoost'); RemoveAbility('area_nml'); RemoveAbility('area_skellige'); inv.RemoveItemByTag('GwintCard', -1); horseInventory.RemoveItemByTag('GwintCard', -1); inv.RemoveItemByTag('ReadableItem', -1); horseInventory.RemoveItemByTag('ReadableItem', -1); abilityManager.RestoreStats(); ((W3PlayerAbilityManager)abilityManager).RemoveToxicityOffset(10000); GetInventory().SingletonItemsRefillAmmo(); craftingSchematics.Clear(); AddStartingSchematics(); for( i=0; i { amountOfSetPiecesEquipped[i] = 0; } inv.AddAnItem('Clearing Potion', 1, true, false, false); inv.RemoveItemByName('q203_broken_eyeofloki', -1); horseInventory.RemoveItemByName('q203_broken_eyeofloki', -1); NewGamePlusReplaceViperSet(inv); NewGamePlusReplaceViperSet(horseInventory); NewGamePlusReplaceLynxSet(inv); NewGamePlusReplaceLynxSet(horseInventory); NewGamePlusReplaceGryphonSet(inv); NewGamePlusReplaceGryphonSet(horseInventory); NewGamePlusReplaceBearSet(inv); NewGamePlusReplaceBearSet(horseInventory); NewGamePlusReplaceEP1(inv); NewGamePlusReplaceEP1(horseInventory); NewGamePlusReplaceEP2WitcherSets(inv); NewGamePlusReplaceEP2WitcherSets(horseInventory); NewGamePlusReplaceEP2Items(inv); NewGamePlusReplaceEP2Items(horseInventory); NewGamePlusMarkItemsToNotAdjust(inv); NewGamePlusMarkItemsToNotAdjust(horseInventory); inputHandler.ClearLocksForNGP(); buffImmunities.Clear(); buffRemovedImmunities.Clear(); newGamePlusInitialized = true; m_quenReappliedCount = 1; } private final function NewGamePlusMarkItemsToNotAdjust(out inv : CInventoryComponent) { var ids : array; var i : int; var n : name; inv.GetAllItems(ids); for( i=0; i { inv.SetItemModifierInt(ids[i], 'NGPItemAdjusted', 1); } } private final function NewGamePlusReplaceItem( item : name, new_item : name, out inv : CInventoryComponent) { var i, j : int; var ids, new_ids, enh_ids : array; var dye_ids : array; var enh : array; var wasEquipped : bool; var wasEnchanted : bool; var wasDyed : bool; var enchantName, colorName : name; if ( inv.HasItem( item ) ) { ids = inv.GetItemsIds(item); for (i = 0; i < ids.Size(); i += 1) { inv.GetItemEnhancementItems( ids[i], enh ); wasEnchanted = inv.IsItemEnchanted( ids[i] ); if ( wasEnchanted ) enchantName = inv.GetEnchantment( ids[i] ); wasEquipped = IsItemEquipped( ids[i] ); wasDyed = inv.IsItemColored( ids[i] ); if ( wasDyed ) { colorName = inv.GetItemColor( ids[i] ); } inv.RemoveItem( ids[i], 1 ); new_ids = inv.AddAnItem( new_item, 1, true, true, false ); if ( wasEquipped ) { EquipItem( new_ids[0] ); } if ( wasEnchanted ) { inv.EnchantItem( new_ids[0], enchantName, getEnchamtmentStatName(enchantName) ); } for (j = 0; j < enh.Size(); j += 1) { enh_ids = inv.AddAnItem( enh[j], 1, true, true, false ); inv.EnhanceItemScript( new_ids[0], enh_ids[0] ); } if ( wasDyed ) { dye_ids = inv.AddAnItem( colorName, 1, true, true, false ); inv.ColorItem( new_ids[0], dye_ids[0] ); inv.RemoveItem( dye_ids[0], 1 ); } inv.SetItemModifierInt( new_ids[0], 'NGPItemAdjusted', 1 ); } } } private final function NewGamePlusAdjustDLCItem(item : name, mod : name, inv : CInventoryComponent) { var ids : array; var i : int; if( inv.HasItem(item) ) { ids = inv.GetItemsIds(item); for (i = 0; i < ids.Size(); i += 1) { if ( inv.GetItemModifierInt(ids[i], 'DoNotAdjustNGPDLC') <= 0 ) { inv.AddItemBaseAbility(ids[i], mod); inv.SetItemModifierInt(ids[i], 'DoNotAdjustNGPDLC', 1); } } } } private final function NewGamePlusAdjustDLC1TemerianSet(inv : CInventoryComponent) { NewGamePlusAdjustDLCItem('NGP DLC1 Temerian Armor', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC1 Temerian Gloves', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC1 Temerian Pants', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC1 Temerian Boots', 'NGP DLC Compatibility Armor Mod', inv); } private final function NewGamePlusAdjustDLC5NilfgardianSet(inv : CInventoryComponent) { NewGamePlusAdjustDLCItem('NGP DLC5 Nilfgaardian Armor', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC5 Nilfgaardian Gloves', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC5 Nilfgaardian Pants', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC5 Nilfgaardian Boots', 'NGP DLC Compatibility Armor Mod', inv); } private final function NewGamePlusAdjustDLC10WolfSet(inv : CInventoryComponent) { NewGamePlusAdjustDLCItem('NGP Wolf Armor', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Armor 1', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Armor 2', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Armor 3', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Boots 1', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Boots 2', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Boots 3', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Boots 4', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Gloves 1', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Gloves 2', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Gloves 3', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Gloves 4', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Pants 1', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Pants 2', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Pants 3', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf Pants 4', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School steel sword', 'NGP Wolf Steel Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School steel sword 1', 'NGP Wolf Steel Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School steel sword 2', 'NGP Wolf Steel Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School steel sword 3', 'NGP Wolf Steel Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School silver sword', 'NGP Wolf Silver Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School silver sword 1', 'NGP Wolf Silver Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School silver sword 2', 'NGP Wolf Silver Sword Mod', inv); NewGamePlusAdjustDLCItem('NGP Wolf School silver sword 3', 'NGP Wolf Silver Sword Mod', inv); } private final function NewGamePlusAdjustDLC14SkelligeSet(inv : CInventoryComponent) { NewGamePlusAdjustDLCItem('NGP DLC14 Skellige Armor', 'NGP DLC Compatibility Chest Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC14 Skellige Gloves', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC14 Skellige Pants', 'NGP DLC Compatibility Armor Mod', inv); NewGamePlusAdjustDLCItem('NGP DLC14 Skellige Boots', 'NGP DLC Compatibility Armor Mod', inv); } private final function NewGamePlusReplaceViperSet(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Viper School steel sword', 'NGP Viper School steel sword', inv); NewGamePlusReplaceItem('Viper School silver sword', 'NGP Viper School silver sword', inv); } private final function NewGamePlusReplaceLynxSet(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Lynx Armor', 'NGP Lynx Armor', inv); NewGamePlusReplaceItem('Lynx Armor 1', 'NGP Lynx Armor 1', inv); NewGamePlusReplaceItem('Lynx Armor 2', 'NGP Lynx Armor 2', inv); NewGamePlusReplaceItem('Lynx Armor 3', 'NGP Lynx Armor 3', inv); NewGamePlusReplaceItem('Lynx Gloves 1', 'NGP Lynx Gloves 1', inv); NewGamePlusReplaceItem('Lynx Gloves 2', 'NGP Lynx Gloves 2', inv); NewGamePlusReplaceItem('Lynx Gloves 3', 'NGP Lynx Gloves 3', inv); NewGamePlusReplaceItem('Lynx Gloves 4', 'NGP Lynx Gloves 4', inv); NewGamePlusReplaceItem('Lynx Pants 1', 'NGP Lynx Pants 1', inv); NewGamePlusReplaceItem('Lynx Pants 2', 'NGP Lynx Pants 2', inv); NewGamePlusReplaceItem('Lynx Pants 3', 'NGP Lynx Pants 3', inv); NewGamePlusReplaceItem('Lynx Pants 4', 'NGP Lynx Pants 4', inv); NewGamePlusReplaceItem('Lynx Boots 1', 'NGP Lynx Boots 1', inv); NewGamePlusReplaceItem('Lynx Boots 2', 'NGP Lynx Boots 2', inv); NewGamePlusReplaceItem('Lynx Boots 3', 'NGP Lynx Boots 3', inv); NewGamePlusReplaceItem('Lynx Boots 4', 'NGP Lynx Boots 4', inv); NewGamePlusReplaceItem('Lynx School steel sword', 'NGP Lynx School steel sword', inv); NewGamePlusReplaceItem('Lynx School steel sword 1', 'NGP Lynx School steel sword 1', inv); NewGamePlusReplaceItem('Lynx School steel sword 2', 'NGP Lynx School steel sword 2', inv); NewGamePlusReplaceItem('Lynx School steel sword 3', 'NGP Lynx School steel sword 3', inv); NewGamePlusReplaceItem('Lynx School silver sword', 'NGP Lynx School silver sword', inv); NewGamePlusReplaceItem('Lynx School silver sword 1', 'NGP Lynx School silver sword 1', inv); NewGamePlusReplaceItem('Lynx School silver sword 2', 'NGP Lynx School silver sword 2', inv); NewGamePlusReplaceItem('Lynx School silver sword 3', 'NGP Lynx School silver sword 3', inv); } private final function NewGamePlusReplaceGryphonSet(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Gryphon Armor', 'NGP Gryphon Armor', inv); NewGamePlusReplaceItem('Gryphon Armor 1', 'NGP Gryphon Armor 1', inv); NewGamePlusReplaceItem('Gryphon Armor 2', 'NGP Gryphon Armor 2', inv); NewGamePlusReplaceItem('Gryphon Armor 3', 'NGP Gryphon Armor 3', inv); NewGamePlusReplaceItem('Gryphon Gloves 1', 'NGP Gryphon Gloves 1', inv); NewGamePlusReplaceItem('Gryphon Gloves 2', 'NGP Gryphon Gloves 2', inv); NewGamePlusReplaceItem('Gryphon Gloves 3', 'NGP Gryphon Gloves 3', inv); NewGamePlusReplaceItem('Gryphon Gloves 4', 'NGP Gryphon Gloves 4', inv); NewGamePlusReplaceItem('Gryphon Pants 1', 'NGP Gryphon Pants 1', inv); NewGamePlusReplaceItem('Gryphon Pants 2', 'NGP Gryphon Pants 2', inv); NewGamePlusReplaceItem('Gryphon Pants 3', 'NGP Gryphon Pants 3', inv); NewGamePlusReplaceItem('Gryphon Pants 4', 'NGP Gryphon Pants 4', inv); NewGamePlusReplaceItem('Gryphon Boots 1', 'NGP Gryphon Boots 1', inv); NewGamePlusReplaceItem('Gryphon Boots 2', 'NGP Gryphon Boots 2', inv); NewGamePlusReplaceItem('Gryphon Boots 3', 'NGP Gryphon Boots 3', inv); NewGamePlusReplaceItem('Gryphon Boots 4', 'NGP Gryphon Boots 4', inv); NewGamePlusReplaceItem('Gryphon School steel sword', 'NGP Gryphon School steel sword', inv); NewGamePlusReplaceItem('Gryphon School steel sword 1', 'NGP Gryphon School steel sword 1', inv); NewGamePlusReplaceItem('Gryphon School steel sword 2', 'NGP Gryphon School steel sword 2', inv); NewGamePlusReplaceItem('Gryphon School steel sword 3', 'NGP Gryphon School steel sword 3', inv); NewGamePlusReplaceItem('Gryphon School silver sword', 'NGP Gryphon School silver sword', inv); NewGamePlusReplaceItem('Gryphon School silver sword 1', 'NGP Gryphon School silver sword 1', inv); NewGamePlusReplaceItem('Gryphon School silver sword 2', 'NGP Gryphon School silver sword 2', inv); NewGamePlusReplaceItem('Gryphon School silver sword 3', 'NGP Gryphon School silver sword 3', inv); } private final function NewGamePlusReplaceBearSet(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Bear Armor', 'NGP Bear Armor', inv); NewGamePlusReplaceItem('Bear Armor 1', 'NGP Bear Armor 1', inv); NewGamePlusReplaceItem('Bear Armor 2', 'NGP Bear Armor 2', inv); NewGamePlusReplaceItem('Bear Armor 3', 'NGP Bear Armor 3', inv); NewGamePlusReplaceItem('Bear Gloves 1', 'NGP Bear Gloves 1', inv); NewGamePlusReplaceItem('Bear Gloves 2', 'NGP Bear Gloves 2', inv); NewGamePlusReplaceItem('Bear Gloves 3', 'NGP Bear Gloves 3', inv); NewGamePlusReplaceItem('Bear Gloves 4', 'NGP Bear Gloves 4', inv); NewGamePlusReplaceItem('Bear Pants 1', 'NGP Bear Pants 1', inv); NewGamePlusReplaceItem('Bear Pants 2', 'NGP Bear Pants 2', inv); NewGamePlusReplaceItem('Bear Pants 3', 'NGP Bear Pants 3', inv); NewGamePlusReplaceItem('Bear Pants 4', 'NGP Bear Pants 4', inv); NewGamePlusReplaceItem('Bear Boots 1', 'NGP Bear Boots 1', inv); NewGamePlusReplaceItem('Bear Boots 2', 'NGP Bear Boots 2', inv); NewGamePlusReplaceItem('Bear Boots 3', 'NGP Bear Boots 3', inv); NewGamePlusReplaceItem('Bear Boots 4', 'NGP Bear Boots 4', inv); NewGamePlusReplaceItem('Bear School steel sword', 'NGP Bear School steel sword', inv); NewGamePlusReplaceItem('Bear School steel sword 1', 'NGP Bear School steel sword 1', inv); NewGamePlusReplaceItem('Bear School steel sword 2', 'NGP Bear School steel sword 2', inv); NewGamePlusReplaceItem('Bear School steel sword 3', 'NGP Bear School steel sword 3', inv); NewGamePlusReplaceItem('Bear School silver sword', 'NGP Bear School silver sword', inv); NewGamePlusReplaceItem('Bear School silver sword 1', 'NGP Bear School silver sword 1', inv); NewGamePlusReplaceItem('Bear School silver sword 2', 'NGP Bear School silver sword 2', inv); NewGamePlusReplaceItem('Bear School silver sword 3', 'NGP Bear School silver sword 3', inv); } private final function NewGamePlusReplaceEP1(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Ofir Armor', 'NGP Ofir Armor', inv); NewGamePlusReplaceItem('Ofir Sabre 2', 'NGP Ofir Sabre 2', inv); NewGamePlusReplaceItem('Crafted Burning Rose Armor', 'NGP Crafted Burning Rose Armor', inv); NewGamePlusReplaceItem('Crafted Burning Rose Gloves', 'NGP Crafted Burning Rose Gloves', inv); NewGamePlusReplaceItem('Crafted Burning Rose Sword', 'NGP Crafted Burning Rose Sword', inv); NewGamePlusReplaceItem('Crafted Ofir Armor', 'NGP Crafted Ofir Armor', inv); NewGamePlusReplaceItem('Crafted Ofir Boots', 'NGP Crafted Ofir Boots', inv); NewGamePlusReplaceItem('Crafted Ofir Gloves', 'NGP Crafted Ofir Gloves', inv); NewGamePlusReplaceItem('Crafted Ofir Pants', 'NGP Crafted Ofir Pants', inv); NewGamePlusReplaceItem('Crafted Ofir Steel Sword', 'NGP Crafted Ofir Steel Sword', inv); NewGamePlusReplaceItem('EP1 Crafted Witcher Silver Sword', 'NGP EP1 Crafted Witcher Silver Sword', inv); NewGamePlusReplaceItem('Olgierd Sabre', 'NGP Olgierd Sabre', inv); NewGamePlusReplaceItem('EP1 Witcher Armor', 'NGP EP1 Witcher Armor', inv); NewGamePlusReplaceItem('EP1 Witcher Boots', 'NGP EP1 Witcher Boots', inv); NewGamePlusReplaceItem('EP1 Witcher Gloves', 'NGP EP1 Witcher Gloves', inv); NewGamePlusReplaceItem('EP1 Witcher Pants', 'NGP EP1 Witcher Pants', inv); NewGamePlusReplaceItem('EP1 Viper School steel sword', 'NGP EP1 Viper School steel sword', inv); NewGamePlusReplaceItem('EP1 Viper School silver sword', 'NGP EP1 Viper School silver sword', inv); } private final function NewGamePlusReplaceEP2WitcherSets(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Lynx Armor 4', 'NGP Lynx Armor 4', inv); NewGamePlusReplaceItem('Gryphon Armor 4', 'NGP Gryphon Armor 4', inv); NewGamePlusReplaceItem('Bear Armor 4', 'NGP Bear Armor 4', inv); NewGamePlusReplaceItem('Wolf Armor 4', 'NGP Wolf Armor 4', inv); NewGamePlusReplaceItem('Red Wolf Armor 1', 'NGP Red Wolf Armor 1', inv); NewGamePlusReplaceItem('Lynx Gloves 5', 'NGP Lynx Gloves 5', inv); NewGamePlusReplaceItem('Gryphon Gloves 5', 'NGP Gryphon Gloves 5', inv); NewGamePlusReplaceItem('Bear Gloves 5', 'NGP Bear Gloves 5', inv); NewGamePlusReplaceItem('Wolf Gloves 5', 'NGP Wolf Gloves 5', inv); NewGamePlusReplaceItem('Red Wolf Gloves 1', 'NGP Red Wolf Gloves 1', inv); NewGamePlusReplaceItem('Lynx Pants 5', 'NGP Lynx Pants 5', inv); NewGamePlusReplaceItem('Gryphon Pants 5', 'NGP Gryphon Pants 5', inv); NewGamePlusReplaceItem('Bear Pants 5', 'NGP Bear Pants 5', inv); NewGamePlusReplaceItem('Wolf Pants 5', 'NGP Wolf Pants 5', inv); NewGamePlusReplaceItem('Red Wolf Pants 1', 'NGP Red Wolf Pants 1', inv); NewGamePlusReplaceItem('Lynx Boots 5', 'NGP Lynx Boots 5', inv); NewGamePlusReplaceItem('Gryphon Boots 5', 'NGP Gryphon Boots 5', inv); NewGamePlusReplaceItem('Bear Boots 5', 'NGP Bear Boots 5', inv); NewGamePlusReplaceItem('Wolf Boots 5', 'NGP Wolf Boots 5', inv); NewGamePlusReplaceItem('Red Wolf Boots 1', 'NGP Red Wolf Boots 1', inv); NewGamePlusReplaceItem('Lynx School steel sword 4', 'NGP Lynx School steel sword 4', inv); NewGamePlusReplaceItem('Gryphon School steel sword 4', 'NGP Gryphon School steel sword 4', inv); NewGamePlusReplaceItem('Bear School steel sword 4', 'NGP Bear School steel sword 4', inv); NewGamePlusReplaceItem('Wolf School steel sword 4', 'NGP Wolf School steel sword 4', inv); NewGamePlusReplaceItem('Red Wolf School steel sword 1', 'NGP Red Wolf School steel sword 1', inv); NewGamePlusReplaceItem('Lynx School silver sword 4', 'NGP Lynx School silver sword 4', inv); NewGamePlusReplaceItem('Gryphon School silver sword 4', 'NGP Gryphon School silver sword 4', inv); NewGamePlusReplaceItem('Bear School silver sword 4', 'NGP Bear School silver sword 4', inv); NewGamePlusReplaceItem('Wolf School silver sword 4', 'NGP Wolf School silver sword 4', inv); NewGamePlusReplaceItem('Red Wolf School silver sword 1', 'NGP Red Wolf School silver sword 1', inv); } private final function NewGamePlusReplaceEP2Items(out inv : CInventoryComponent) { NewGamePlusReplaceItem('Guard Lvl1 Armor 3', 'NGP Guard Lvl1 Armor 3', inv); NewGamePlusReplaceItem('Guard Lvl1 A Armor 3', 'NGP Guard Lvl1 A Armor 3', inv); NewGamePlusReplaceItem('Guard Lvl2 Armor 3', 'NGP Guard Lvl2 Armor 3', inv); NewGamePlusReplaceItem('Guard Lvl2 A Armor 3', 'NGP Guard Lvl2 A Armor 3', inv); NewGamePlusReplaceItem('Knight Geralt Armor 3', 'NGP Knight Geralt Armor 3', inv); NewGamePlusReplaceItem('Knight Geralt A Armor 3', 'NGP Knight Geralt A Armor 3', inv); NewGamePlusReplaceItem('q702_vampire_armor', 'NGP q702_vampire_armor', inv); NewGamePlusReplaceItem('Guard Lvl1 Gloves 3', 'NGP Guard Lvl1 Gloves 3', inv); NewGamePlusReplaceItem('Guard Lvl1 A Gloves 3', 'NGP Guard Lvl1 A Gloves 3', inv); NewGamePlusReplaceItem('Guard Lvl2 Gloves 3', 'NGP Guard Lvl2 Gloves 3', inv); NewGamePlusReplaceItem('Guard Lvl2 A Gloves 3', 'NGP Guard Lvl2 A Gloves 3', inv); NewGamePlusReplaceItem('Knight Geralt Gloves 3', 'NGP Knight Geralt Gloves 3', inv); NewGamePlusReplaceItem('Knight Geralt A Gloves 3', 'NGP Knight Geralt A Gloves 3', inv); NewGamePlusReplaceItem('q702_vampire_gloves', 'NGP q702_vampire_gloves', inv); NewGamePlusReplaceItem('Guard Lvl1 Pants 3', 'NGP Guard Lvl1 Pants 3', inv); NewGamePlusReplaceItem('Guard Lvl1 A Pants 3', 'NGP Guard Lvl1 A Pants 3', inv); NewGamePlusReplaceItem('Guard Lvl2 Pants 3', 'NGP Guard Lvl2 Pants 3', inv); NewGamePlusReplaceItem('Guard Lvl2 A Pants 3', 'NGP Guard Lvl2 A Pants 3', inv); NewGamePlusReplaceItem('Knight Geralt Pants 3', 'NGP Knight Geralt Pants 3', inv); NewGamePlusReplaceItem('Knight Geralt A Pants 3', 'NGP Knight Geralt A Pants 3', inv); NewGamePlusReplaceItem('q702_vampire_pants', 'NGP q702_vampire_pants', inv); NewGamePlusReplaceItem('Guard Lvl1 Boots 3', 'NGP Guard Lvl1 Boots 3', inv); NewGamePlusReplaceItem('Guard Lvl1 A Boots 3', 'NGP Guard Lvl1 A Boots 3', inv); NewGamePlusReplaceItem('Guard Lvl2 Boots 3', 'NGP Guard Lvl2 Boots 3', inv); NewGamePlusReplaceItem('Guard Lvl2 A Boots 3', 'NGP Guard Lvl2 A Boots 3', inv); NewGamePlusReplaceItem('Knight Geralt Boots 3', 'NGP Knight Geralt Boots 3', inv); NewGamePlusReplaceItem('Knight Geralt A Boots 3', 'NGP Knight Geralt A Boots 3', inv); NewGamePlusReplaceItem('q702_vampire_boots', 'NGP q702_vampire_boots', inv); NewGamePlusReplaceItem('Serpent Steel Sword 1', 'NGP Serpent Steel Sword 1', inv); NewGamePlusReplaceItem('Serpent Steel Sword 2', 'NGP Serpent Steel Sword 2', inv); NewGamePlusReplaceItem('Serpent Steel Sword 3', 'NGP Serpent Steel Sword 3', inv); NewGamePlusReplaceItem('Guard lvl1 steel sword 3', 'NGP Guard lvl1 steel sword 3', inv); NewGamePlusReplaceItem('Guard lvl2 steel sword 3', 'NGP Guard lvl2 steel sword 3', inv); NewGamePlusReplaceItem('Knights steel sword 3', 'NGP Knights steel sword 3', inv); NewGamePlusReplaceItem('Hanza steel sword 3', 'NGP Hanza steel sword 3', inv); NewGamePlusReplaceItem('Toussaint steel sword 3', 'NGP Toussaint steel sword 3', inv); NewGamePlusReplaceItem('q702 vampire steel sword', 'NGP q702 vampire steel sword', inv); NewGamePlusReplaceItem('Serpent Silver Sword 1', 'NGP Serpent Silver Sword 1', inv); NewGamePlusReplaceItem('Serpent Silver Sword 2', 'NGP Serpent Silver Sword 2', inv); NewGamePlusReplaceItem('Serpent Silver Sword 3', 'NGP Serpent Silver Sword 3', inv); } public function GetEquippedSword(steel : bool) : SItemUniqueId { var item : SItemUniqueId; if(steel) GetItemEquippedOnSlot(EES_SteelSword, item); else GetItemEquippedOnSlot(EES_SilverSword, item); return item; } timer function BroadcastRain( deltaTime : float, id : int ) { var rainStrength : float = 0; rainStrength = GetRainStrength(); if( rainStrength > 0.5 ) { theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( thePlayer, 'RainAction', 2.0f , 50.0f, -1.f, -1, true); LogReactionSystem( "'RainAction' was sent by Player - single broadcast - distance: 50.0" ); } } function InitializeParryType() { var i, j : int; parryTypeTable.Resize( EnumGetMax('EAttackSwingType')+1 ); for( i = 0; i < EnumGetMax('EAttackSwingType')+1; i += 1 ) { parryTypeTable[i].Resize( EnumGetMax('EAttackSwingDirection')+1 ); } parryTypeTable[AST_Horizontal][ASD_UpDown] = PT_None; parryTypeTable[AST_Horizontal][ASD_DownUp] = PT_None; parryTypeTable[AST_Horizontal][ASD_LeftRight] = PT_Left; parryTypeTable[AST_Horizontal][ASD_RightLeft] = PT_Right; parryTypeTable[AST_Vertical][ASD_UpDown] = PT_Up; parryTypeTable[AST_Vertical][ASD_DownUp] = PT_Down; parryTypeTable[AST_Vertical][ASD_LeftRight] = PT_None; parryTypeTable[AST_Vertical][ASD_RightLeft] = PT_None; parryTypeTable[AST_DiagonalUp][ASD_UpDown] = PT_None; parryTypeTable[AST_DiagonalUp][ASD_DownUp] = PT_None; parryTypeTable[AST_DiagonalUp][ASD_LeftRight] = PT_UpLeft; parryTypeTable[AST_DiagonalUp][ASD_RightLeft] = PT_RightUp; parryTypeTable[AST_DiagonalDown][ASD_UpDown] = PT_None; parryTypeTable[AST_DiagonalDown][ASD_DownUp] = PT_None; parryTypeTable[AST_DiagonalDown][ASD_LeftRight] = PT_LeftDown; parryTypeTable[AST_DiagonalDown][ASD_RightLeft] = PT_DownRight; parryTypeTable[AST_Jab][ASD_UpDown] = PT_Jab; parryTypeTable[AST_Jab][ASD_DownUp] = PT_Jab; parryTypeTable[AST_Jab][ASD_LeftRight] = PT_Jab; parryTypeTable[AST_Jab][ASD_RightLeft] = PT_Jab; } event OnDeath( damageAction : W3DamageAction ) { var items : array< SItemUniqueId >; var i, size : int; var slot : EEquipmentSlots; var holdSlot : name; super.OnDeath( damageAction ); items = GetHeldItems(); if( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait') { OnRangedForceHolster( true, true, true ); rangedWeapon.ClearDeployedEntity(true); } size = items.Size(); if ( size > 0 ) { for ( i = 0; i < size; i += 1 ) { if ( this.inv.IsIdValid( items[i] ) && !( this.inv.IsItemCrossbow( items[i] ) ) ) { holdSlot = this.inv.GetItemHoldSlot( items[i] ); if ( holdSlot == 'l_weapon' && this.IsHoldingItemInLHand() ) { this.OnUseSelectedItem( true ); } DropItemFromSlot( holdSlot, false ); if ( holdSlot == 'r_weapon' ) { slot = this.GetItemSlot( items[i] ); if ( UnequipItemFromSlot( slot ) ) Log( "Unequip" ); } } } } } function HandleMovement( deltaTime : float ) { super.HandleMovement( deltaTime ); rawCameraHeading = theCamera.GetCameraHeading(); } function ToggleSpecialAttackHeavyAllowed( toggle : bool) { specialAttackHeavyAllowed = toggle; } function GetReputationManager() : W3Reputation { return reputationManager; } function OnRadialMenuItemChoose( selectedItem : string ) { var iSlotId : int; var item : SItemUniqueId; if ( selectedItem != "Crossbow" ) { if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) OnRangedForceHolster( true, false ); } switch(selectedItem) { case "Meditation": theGame.RequestMenuWithBackground( 'MeditationClockMenu', 'CommonMenu' ); break; case "Slot1": GetItemEquippedOnSlot( EES_Petard1, item ); if( thePlayer.inv.IsIdValid( item ) ) { SelectQuickslotItem( EES_Petard1 ); } else { SelectQuickslotItem( EES_Petard2 ); } break; case "Slot2": GetItemEquippedOnSlot( EES_Petard2, item ); if( thePlayer.inv.IsIdValid( item ) ) { SelectQuickslotItem( EES_Petard2 ); } else { SelectQuickslotItem( EES_Petard1 ); } break; case "Crossbow": SelectQuickslotItem(EES_RangedWeapon); break; case "Slot3": GetItemEquippedOnSlot( EES_Quickslot1, item ); if( thePlayer.inv.IsIdValid( item ) ) { SelectQuickslotItem( EES_Quickslot1 ); } else { SelectQuickslotItem( EES_Quickslot2 ); } break; case "Slot4": GetItemEquippedOnSlot( EES_Quickslot2, item ); if( thePlayer.inv.IsIdValid( item ) ) { SelectQuickslotItem( EES_Quickslot2 ); } else { SelectQuickslotItem( EES_Quickslot1 ); } break; default: SetEquippedSign(SignStringToEnum( selectedItem )); FactsRemove("SignToggled"); break; } } function ToggleNextItem() { var quickSlotItems : array< EEquipmentSlots >; var currentSelectedItem : SItemUniqueId; var item : SItemUniqueId; var i : int; for( i = EES_Quickslot2; i > EES_Petard1 - 1; i -= 1 ) { GetItemEquippedOnSlot( i, item ); if( inv.IsIdValid( item ) ) { quickSlotItems.PushBack( i ); } } if( !quickSlotItems.Size() ) { return; } currentSelectedItem = GetSelectedItemId(); if( inv.IsIdValid( currentSelectedItem ) ) { for( i = 0; i < quickSlotItems.Size(); i += 1 ) { GetItemEquippedOnSlot( quickSlotItems[i], item ); if( currentSelectedItem == item ) { if( i == quickSlotItems.Size() - 1 ) { SelectQuickslotItem( quickSlotItems[ 0 ] ); } else { SelectQuickslotItem( quickSlotItems[ i + 1 ] ); } return; } } } else { SelectQuickslotItem( quickSlotItems[ 0 ] ); } } function SetEquippedSign( signType : ESignType ) { if(!IsSignBlocked(signType)) { equippedSign = signType; FactsSet("CurrentlySelectedSign", equippedSign); } } function GetEquippedSign() : ESignType { return equippedSign; } function GetCurrentlyCastSign() : ESignType { return currentlyCastSign; } function SetCurrentlyCastSign( type : ESignType, entity : W3SignEntity ) { currentlyCastSign = type; if( type != ST_None ) { signs[currentlyCastSign].entity = entity; } } function GetCurrentSignEntity() : W3SignEntity { if(currentlyCastSign == ST_None) return NULL; return signs[currentlyCastSign].entity; } public function GetSignEntity(type : ESignType) : W3SignEntity { if(type == ST_None) return NULL; return signs[type].entity; } public function GetSignTemplate(type : ESignType) : CEntityTemplate { if(type == ST_None) return NULL; return signs[type].template; } public function IsCurrentSignChanneled() : bool { if( currentlyCastSign != ST_None && signs[currentlyCastSign].entity) return signs[currentlyCastSign].entity.OnCheckChanneling(); return false; } function IsCastingSign() : bool { return currentlyCastSign != ST_None; } protected function IsInCombatActionCameraRotationEnabled() : bool { if( IsInCombatAction() && ( GetCombatAction() == EBAT_EMPTY || GetCombatAction() == EBAT_Parry ) ) { return true; } return !bIsInCombatAction; } function SetHoldBeforeOpenRadialMenuTime ( time : float ) { _HoldBeforeOpenRadialMenuTime = time; } public function RepairItem ( rapairKitId : SItemUniqueId, usedOnItem : SItemUniqueId ) { var itemMaxDurablity : float; var itemCurrDurablity : float; var baseRepairValue : float; var reapirValue : float; var itemAttribute : SAbilityAttributeValue; itemMaxDurablity = inv.GetItemMaxDurability(usedOnItem); itemCurrDurablity = inv.GetItemDurability(usedOnItem); itemAttribute = inv.GetItemAttributeValue ( rapairKitId, 'repairValue' ); if( itemCurrDurablity >= itemMaxDurablity ) { return; } if ( inv.IsItemAnyArmor ( usedOnItem )|| inv.IsItemWeapon( usedOnItem ) ) { baseRepairValue = itemMaxDurablity * itemAttribute.valueMultiplicative; reapirValue = MinF( itemCurrDurablity + baseRepairValue, itemMaxDurablity ); inv.SetItemDurabilityScript ( usedOnItem, MinF ( reapirValue, itemMaxDurablity )); } inv.RemoveItem ( rapairKitId, 1 ); } public function HasRepairAbleGearEquiped ( ) : bool { var curEquipedItem : SItemUniqueId; return ( GetItemEquippedOnSlot(EES_Armor, curEquipedItem) || GetItemEquippedOnSlot(EES_Boots, curEquipedItem) || GetItemEquippedOnSlot(EES_Pants, curEquipedItem) || GetItemEquippedOnSlot(EES_Gloves, curEquipedItem)) == true; } public function HasRepairAbleWaponEquiped () : bool { var curEquipedItem : SItemUniqueId; return ( GetItemEquippedOnSlot(EES_SilverSword, curEquipedItem) || GetItemEquippedOnSlot(EES_SteelSword, curEquipedItem) ) == true; } public function IsItemRepairAble ( item : SItemUniqueId ) : bool { return inv.GetItemDurabilityRatio(item) <= 0.99999f; } public function ApplyOil( oilId : SItemUniqueId, usedOnItem : SItemUniqueId ) : bool { var tutStateOil : W3TutorialManagerUIHandlerStateOils; if( !super.ApplyOil( oilId, usedOnItem )) return false; if(ShouldProcessTutorial('TutorialOilCanEquip3')) { tutStateOil = (W3TutorialManagerUIHandlerStateOils)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutStateOil) { tutStateOil.OnOilApplied(); } } return true; } private final function RemoveExtraOilsFromItem( item : SItemUniqueId ) { var oils : array< CBaseGameplayEffect >; var i, cnt : int; var buff : W3Effect_Oil; oils = GetBuffs( EET_Oil ); for( i=0; i { buff = (W3Effect_Oil) oils[ i ]; if( buff && buff.GetSwordItemId() == item ) { cnt += 1; } } while( cnt > 1 ) { inv.RemoveOldestOilFromItem( item ); cnt -= 1; } } function ReduceDamage(out damageData : W3DamageAction) { var actorAttacker : CActor; var quen : W3QuenEntity; var attackRange : CAIAttackRange; var attackerMovementAdjustor : CMovementAdjustor; var dist, distToAttacker, actionHeading, attackerHeading, currAdrenaline, adrenReducedDmg, focus : float; var attackName : name; var useQuenForBleeding : bool; var min, max : SAbilityAttributeValue; var skillLevel : int; super.ReduceDamage(damageData); quen = (W3QuenEntity)signs[ST_Quen].entity; useQuenForBleeding = false; if(quen && !damageData.DealsAnyDamage() && ((W3Effect_Bleeding)damageData.causer) && damageData.GetDamageValue(theGame.params.DAMAGE_NAME_DIRECT) > 0.f) useQuenForBleeding = true; if(!useQuenForBleeding && !damageData.DealsAnyDamage()) return; actorAttacker = (CActor)damageData.attacker; if(actorAttacker && IsCurrentlyDodging() && damageData.CanBeDodged()) { actionHeading = evadeHeading; attackerHeading = actorAttacker.GetHeading(); dist = AngleDistance(actionHeading, attackerHeading); distToAttacker = VecDistance(this.GetWorldPosition(),damageData.attacker.GetWorldPosition()); attackName = actorAttacker.GetLastAttackRangeName(); attackRange = theGame.GetAttackRangeForEntity( actorAttacker, attackName ); attackerMovementAdjustor = actorAttacker.GetMovingAgentComponent().GetMovementAdjustor(); if( ( AbsF(dist) < 150 && attackName != 'stomp' && attackName != 'anchor_special_far' && attackName != 'anchor_far' ) || ( ( attackName == 'stomp' || attackName == 'anchor_special_far' || attackName == 'anchor_far' ) && distToAttacker > attackRange.rangeMax * 0.75 ) ) { if ( theGame.CanLog() ) { LogDMHits("W3PlayerWitcher.ReduceDamage: Attack dodged by player - no damage done", damageData); } damageData.SetAllProcessedDamageAs(0); damageData.SetWasDodged(); } else if( !damageData.IsActionEnvironment() && !damageData.IsDoTDamage() && CanUseSkill( S_Sword_s09 ) ) { skillLevel = GetSkillLevel( S_Sword_s09 ); if( skillLevel == GetSkillMaxLevel( S_Sword_s09 ) ) { damageData.SetAllProcessedDamageAs(0); damageData.SetWasDodged(); } else { damageData.processedDmg.vitalityDamage *= 1 - CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s09, 'damage_reduction', false, true)) * skillLevel; } if ( theGame.CanLog() ) { LogDMHits("W3PlayerWitcher.ReduceDamage: skill S_Sword_s09 reduced damage while dodging", damageData ); } } } if(quen && damageData.GetBuffSourceName() != "FallingDamage") { if ( theGame.CanLog() ) { LogDMHits("W3PlayerWitcher.ReduceDamage: Processing Quen sign damage reduction...", damageData); } quen.OnTargetHit( damageData ); } if( HasBuff( EET_GryphonSetBonusYrden ) ) { min = GetAttributeValue( 'gryphon_set_bns_dmg_reduction' ); damageData.processedDmg.vitalityDamage *= 1 - min.valueAdditive; } if( IsMutationActive( EPMT_Mutation5 ) && !IsAnyQuenActive() && !damageData.IsDoTDamage() ) { focus = GetStat( BCS_Focus ); currAdrenaline = FloorF( focus ); if( currAdrenaline >= 1 ) { theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation5', 'mut5_dmg_red_perc', min, max ); adrenReducedDmg = ( currAdrenaline * min.valueAdditive ); damageData.processedDmg.vitalityDamage *= 1 - adrenReducedDmg; theGame.MutationHUDFeedback( MFT_PlayOnce ); if( focus >= 3.f ) { PlayEffect( 'mutation_5_stage_03' ); } else if( focus >= 2.f ) { PlayEffect( 'mutation_5_stage_02' ); } else { PlayEffect( 'mutation_5_stage_01' ); } } } if(!damageData.GetIgnoreImmortalityMode()) { if(!((W3PlayerWitcher)this)) Log(""); if( IsInvulnerable() ) { if ( theGame.CanLog() ) { LogDMHits("CActor.ReduceDamage: victim Invulnerable - no damage will be dealt", damageData ); } damageData.SetAllProcessedDamageAs(0); return; } if(actorAttacker && damageData.DealsAnyDamage() ) actorAttacker.SignalGameplayEventParamObject( 'DamageInstigated', damageData ); if( IsImmortal() ) { if ( theGame.CanLog() ) { LogDMHits("CActor.ReduceDamage: victim is Immortal, clamping damage", damageData ); } damageData.processedDmg.vitalityDamage = ClampF(damageData.processedDmg.vitalityDamage, 0, GetStat(BCS_Vitality)-1 ); damageData.processedDmg.essenceDamage = ClampF(damageData.processedDmg.essenceDamage, 0, GetStat(BCS_Essence)-1 ); return; } } else { if(actorAttacker && damageData.DealsAnyDamage() ) actorAttacker.SignalGameplayEventParamObject( 'DamageInstigated', damageData ); } } timer function UndyingSkillCooldown(dt : float, id : int) { cannotUseUndyingSkill = false; } event OnTakeDamage( action : W3DamageAction) { var currVitality, rgnVitality, hpTriggerTreshold : float; var healingFactor : float; var abilityName : name; var abilityCount, maxStack, itemDurability : float; var addAbility : bool; var min, max : SAbilityAttributeValue; var mutagenQuen : W3SignEntity; var equipped : array; var i : int; var killSourceName : string; var aerondight : W3Effect_Aerondight; currVitality = GetStat(BCS_Vitality); if(action.processedDmg.vitalityDamage >= currVitality) { killSourceName = action.GetBuffSourceName(); if( killSourceName != "Quest" && killSourceName != "Kill Trigger" && killSourceName != "Trap" && killSourceName != "FallingDamage" ) { if(!cannotUseUndyingSkill && FloorF(GetStat(BCS_Focus)) >= 1 && CanUseSkill(S_Sword_s18) && HasBuff(EET_BattleTrance) ) { healingFactor = CalculateAttributeValue( GetSkillAttributeValue(S_Sword_s18, 'healing_factor', false, true) ); healingFactor *= GetStatMax(BCS_Vitality); healingFactor *= GetStat(BCS_Focus); healingFactor *= 1 + CalculateAttributeValue( GetSkillAttributeValue(S_Sword_s18, 'healing_bonus', false, true) ) * (GetSkillLevel(S_Sword_s18) - 1); ForceSetStat(BCS_Vitality, GetStatMax(BCS_Vitality)); DrainFocus(GetStat(BCS_Focus)); RemoveBuff(EET_BattleTrance); cannotUseUndyingSkill = true; AddTimer('UndyingSkillCooldown', CalculateAttributeValue( GetSkillAttributeValue(S_Sword_s18, 'trigger_delay', false, true) ), false, , , true); } else if( IsMutationActive( EPMT_Mutation11 ) && !HasBuff( EET_Mutation11Debuff ) && !IsInAir() ) { theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation11', 'health_prc', min, max ); action.SetAllProcessedDamageAs( 0 ); OnMutation11Triggered(); } else { equipped = GetEquippedItems(); for(i=0; i { if ( !inv.IsIdValid( equipped[i] ) ) { continue; } itemDurability = inv.GetItemDurability(equipped[i]); if(inv.ItemHasAbility(equipped[i], 'MA_Reinforced') && itemDurability > 0) { inv.SetItemDurabilityScript(equipped[i], MaxF(0, itemDurability - action.processedDmg.vitalityDamage) ); action.processedDmg.vitalityDamage = 0; ForceSetStat(BCS_Vitality, 1); break; } } } } } if(action.DealsAnyDamage() && !((W3Effect_Toxicity)action.causer) ) { if(HasBuff(EET_Mutagen10)) RemoveAbilityAll( GetBuff(EET_Mutagen10).GetAbilityName() ); if(HasBuff(EET_Mutagen15)) RemoveAbilityAll( GetBuff(EET_Mutagen15).GetAbilityName() ); } if(HasBuff(EET_Mutagen19)) { theGame.GetDefinitionsManager().GetAbilityAttributeValue(GetBuff(EET_Mutagen19).GetAbilityName(), 'max_hp_perc_trigger', min, max); hpTriggerTreshold = GetStatMax(BCS_Vitality) * CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); if(action.GetDamageDealt() >= hpTriggerTreshold) { mutagenQuen = (W3SignEntity)theGame.CreateEntity( signs[ST_Quen].template, GetWorldPosition(), GetWorldRotation() ); mutagenQuen.Init( signOwner, signs[ST_Quen].entity, true ); mutagenQuen.OnStarted(); mutagenQuen.OnThrowing(); mutagenQuen.OnEnded(); } } if(action.DealsAnyDamage() && !action.IsDoTDamage() && HasBuff(EET_Mutagen27)) { abilityName = GetBuff(EET_Mutagen27).GetAbilityName(); abilityCount = GetAbilityCount(abilityName); if(abilityCount == 0) { addAbility = true; } else { theGame.GetDefinitionsManager().GetAbilityAttributeValue(abilityName, 'mutagen27_max_stack', min, max); maxStack = CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); if(maxStack >= 0) { addAbility = (abilityCount < maxStack); } else { addAbility = true; } } if(addAbility) { AddAbility(abilityName, true); } } if(HasBuff(EET_Trap) && !action.IsDoTDamage() && action.attacker.HasAbility( 'mon_dettlaff_monster_base' )) { action.AddEffectInfo(EET_Knockdown); RemoveBuff(EET_Trap, true); } super.OnTakeDamage(action); if( !action.WasDodged() && action.DealtDamage() && inv.ItemHasTag( inv.GetCurrentlyHeldSword(), 'Aerondight' ) && !action.IsDoTDamage() && !( (W3Effect_Toxicity) action.causer ) ) { aerondight = (W3Effect_Aerondight)GetBuff( EET_Aerondight ); if( aerondight && aerondight.GetCurrentCount() != 0 ) { aerondight.ReduceAerondightStacks(); } } // if( !action.WasDodged() && action.DealtDamage() && !( (W3Effect_Toxicity) action.causer ) ) // { // RemoveBuff( EET_Mutation3 ); // } // } event OnStartFistfightMinigame() { var i : int; var buffs : array< CBaseGameplayEffect >; effectManager.RemoveAllPotionEffects(); abilityManager.DrainToxicity(GetStatMax( BCS_Toxicity )); buffs = GetBuffs( EET_WellFed ); for( i=buffs.Size()-1; i>=0; i-=1 ) { RemoveEffect( buffs[i] ); } buffs.Clear(); buffs = GetBuffs( EET_WellHydrated ); for( i=buffs.Size()-1; i>=0; i-=1 ) { RemoveEffect( buffs[i] ); } super.OnStartFistfightMinigame(); } event OnEndFistfightMinigame() { super.OnEndFistfightMinigame(); } public function GetCriticalHitChance( isLightAttack : bool, isHeavyAttack : bool, target : CActor, victimMonsterCategory : EMonsterCategory, isBolt : bool ) : float { var ret : float; var thunder : W3Potion_Thunderbolt; var min, max : SAbilityAttributeValue; ret = super.GetCriticalHitChance( isLightAttack, isHeavyAttack, target, victimMonsterCategory, isBolt ); thunder = ( W3Potion_Thunderbolt )GetBuff( EET_Thunderbolt ); if( thunder && thunder.GetBuffLevel() == 3 && GetCurWeather() == EWE_Storm ) { ret += 1.0f; } if( isBolt && IsMutationActive( EPMT_Mutation9 ) ) { theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation9', 'critical_hit_chance', min, max); ret += min.valueMultiplicative; } if( isBolt && CanUseSkill( S_Sword_s07 ) ) { ret += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s07, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s07); } return ret; } public function GetCriticalHitDamageBonus(weaponId : SItemUniqueId, victimMonsterCategory : EMonsterCategory, isStrikeAtBack : bool) : SAbilityAttributeValue { var min, max, bonus, null, oilBonus : SAbilityAttributeValue; var mutagen : CBaseGameplayEffect; var monsterBonusType : name; bonus = super.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, isStrikeAtBack); if( inv.ItemHasActiveOilApplied( weaponId, victimMonsterCategory ) && GetStat( BCS_Focus ) >= 3 && CanUseSkill( S_Alchemy_s07 ) ) { monsterBonusType = MonsterCategoryToAttackPowerBonus( victimMonsterCategory ); oilBonus = inv.GetItemAttributeValue( weaponId, monsterBonusType ); if(oilBonus != null) { bonus += GetSkillAttributeValue(S_Alchemy_s07, theGame.params.CRITICAL_HIT_DAMAGE_BONUS, false, true); } } if (isStrikeAtBack && HasBuff(EET_Mutagen11)) { mutagen = GetBuff(EET_Mutagen11); theGame.GetDefinitionsManager().GetAbilityAttributeValue(mutagen.GetAbilityName(), 'damageIncrease', min, max); bonus += GetAttributeRandomizedValue(min, max); } return bonus; } public function ProcessLockTarget( optional newLockTarget : CActor, optional checkLeftStickHeading : bool ) : bool { var newLockTargetFound : bool; newLockTargetFound = super.ProcessLockTarget(newLockTarget, checkLeftStickHeading); if(GetCurrentlyCastSign() == ST_Axii) { ((W3AxiiEntity)GetCurrentSignEntity()).OnDisplayTargetChange(newLockTarget); } return newLockTargetFound; } event OnProcessActionPost(action : W3DamageAction) { var attackAction : W3Action_Attack; var rendLoad : float; var value : SAbilityAttributeValue; var actorVictim : CActor; var weaponId : SItemUniqueId; var usesSteel, usesSilver, usesVitality, usesEssence : bool; var abs : array; var i : int; var dm : CDefinitionsManagerAccessor; var items : array; var weaponEnt : CEntity; super.OnProcessActionPost(action); attackAction = (W3Action_Attack)action; actorVictim = (CActor)action.victim; if( !actorVictim.IsAlive() ) { return false; } if(attackAction) { if(attackAction.IsActionMelee()) { if(SkillNameToEnum(attackAction.GetAttackTypeName()) == S_Sword_s02) { rendLoad = GetSpecialAttackTimeRatio(); rendLoad = MinF(rendLoad * GetStatMax(BCS_Focus), GetStat(BCS_Focus)); rendLoad = FloorF(rendLoad); DrainFocus(rendLoad); OnSpecialAttackHeavyActionProcess(); } else if(actorVictim && IsRequiredAttitudeBetween(this, actorVictim, true)) { value = GetAttributeValue('focus_gain'); if( FactsQuerySum("debug_fact_focus_boy") > 0 ) { Debug_FocusBoyFocusGain(); } if ( CanUseSkill(S_Sword_s20) ) { value += GetSkillAttributeValue(S_Sword_s20, 'focus_gain', false, true) * GetSkillLevel(S_Sword_s20); } if( IsMutationActive( EPMT_Mutation3 ) && IsRequiredAttitudeBetween( this, action.victim, true ) && !action.victim.HasTag( 'Mutation3InvalidTarget' ) && !attackAction.IsParried() && !attackAction.WasDodged() && !attackAction.IsCountered() && !inv.IsItemFists( attackAction.GetWeaponId() ) && !attackAction.WasDamageReturnedToAttacker() && attackAction.DealtDamage() ) { AddEffectDefault( EET_Mutation3, this, "", false ); } GainStat(BCS_Focus, 0.1f * (1 + CalculateAttributeValue(value)) ); } weaponId = attackAction.GetWeaponId(); if(actorVictim && (ShouldProcessTutorial('TutorialWrongSwordSteel') || ShouldProcessTutorial('TutorialWrongSwordSilver')) && GetAttitudeBetween(actorVictim, this) == AIA_Hostile) { usesSteel = inv.IsItemSteelSwordUsableByPlayer(weaponId); usesSilver = inv.IsItemSilverSwordUsableByPlayer(weaponId); usesVitality = actorVictim.UsesVitality(); usesEssence = actorVictim.UsesEssence(); if(usesSilver && usesVitality) { FactsAdd('tut_wrong_sword_silver',1); } else if(usesSteel && usesEssence) { FactsAdd('tut_wrong_sword_steel',1); } else if(FactsQuerySum('tut_wrong_sword_steel') && usesSilver && usesEssence) { FactsAdd('tut_proper_sword_silver',1); FactsRemove('tut_wrong_sword_steel'); } else if(FactsQuerySum('tut_wrong_sword_silver') && usesSteel && usesVitality) { FactsAdd('tut_proper_sword_steel',1); FactsRemove('tut_wrong_sword_silver'); } } if(!action.WasDodged() && HasAbility('Runeword 1 _Stats', true)) { if(runewordInfusionType == ST_Axii) { actorVictim.SoundEvent('sign_axii_release'); } else if(runewordInfusionType == ST_Igni) { actorVictim.SoundEvent('sign_igni_charge_begin'); } else if(runewordInfusionType == ST_Quen) { value = GetAttributeValue('runeword1_quen_heal'); Heal( action.GetDamageDealt() * value.valueMultiplicative ); PlayEffectSingle('drain_energy_caretaker_shovel'); } else if(runewordInfusionType == ST_Yrden) { actorVictim.SoundEvent('sign_yrden_shock_activate'); } runewordInfusionType = ST_None; items = inv.GetHeldWeapons(); weaponEnt = inv.GetItemEntityUnsafe(items[0]); weaponEnt.StopEffect('runeword_aard'); weaponEnt.StopEffect('runeword_axii'); weaponEnt.StopEffect('runeword_igni'); weaponEnt.StopEffect('runeword_quen'); weaponEnt.StopEffect('runeword_yrden'); } if(ShouldProcessTutorial('TutorialLightAttacks') || ShouldProcessTutorial('TutorialHeavyAttacks')) { if(IsLightAttack(attackAction.GetAttackName())) { theGame.GetTutorialSystem().IncreaseGeraltsLightAttacksCount(action.victim.GetTags()); } else if(IsHeavyAttack(attackAction.GetAttackName())) { theGame.GetTutorialSystem().IncreaseGeraltsHeavyAttacksCount(action.victim.GetTags()); } } } else if(attackAction.IsActionRanged()) { if(CanUseSkill(S_Sword_s15)) { value = GetSkillAttributeValue(S_Sword_s15, 'focus_gain', false, true) * GetSkillLevel(S_Sword_s15) ; GainStat(BCS_Focus, CalculateAttributeValue(value) ); } if(CanUseSkill(S_Sword_s12) && attackAction.IsCriticalHit() && actorVictim) { actorVictim.GetCharacterStats().GetAbilities(abs, false); dm = theGame.GetDefinitionsManager(); for(i=abs.Size()-1; i>=0; i-=1) { if(!dm.AbilityHasTag(abs[i], theGame.params.TAG_MONSTER_SKILL) || actorVictim.IsAbilityBlocked(abs[i])) { abs.EraseFast(i); } } if(abs.Size() > 0) { value = GetSkillAttributeValue(S_Sword_s12, 'duration', true, true) * GetSkillLevel(S_Sword_s12); actorVictim.BlockAbility(abs[ RandRange(abs.Size()) ], true, CalculateAttributeValue(value)); } } } } if( IsMutationActive( EPMT_Mutation10 ) && ( action.IsActionMelee() || action.IsActionWitcherSign() ) ) { PlayEffect( 'mutation_10_energy' ); } if(CanUseSkill(S_Perk_18) && ((W3Petard)action.causer) && action.DealsAnyDamage() && !action.IsDoTDamage()) { value = GetSkillAttributeValue(S_Perk_18, 'focus_gain', false, true); GainStat(BCS_Focus, CalculateAttributeValue(value)); } if( attackAction && IsHeavyAttack( attackAction.GetAttackName() ) && !IsUsingHorse() && attackAction.DealtDamage() && IsSetBonusActive( EISB_Lynx_1 ) && !attackAction.WasDodged() && !attackAction.IsParried() && !attackAction.IsCountered() && ( inv.IsItemSteelSwordUsableByPlayer( attackAction.GetWeaponId() ) || inv.IsItemSilverSwordUsableByPlayer( attackAction.GetWeaponId() ) ) ) { AddEffectDefault( EET_LynxSetBonus, NULL, "HeavyAttack" ); SoundEvent( "ep2_setskill_lynx_activate" ); } } timer function Mutagen14Timer(dt : float, id : int) { var abilityName : name; var abilityCount, maxStack : float; var min, max : SAbilityAttributeValue; var addAbility : bool; abilityName = GetBuff(EET_Mutagen14).GetAbilityName(); abilityCount = GetAbilityCount(abilityName); if(abilityCount == 0) { addAbility = true; } else { theGame.GetDefinitionsManager().GetAbilityAttributeValue(abilityName, 'mutagen14_max_stack', min, max); maxStack = CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); if(maxStack >= 0) { addAbility = (abilityCount < maxStack); } else { addAbility = true; } } if(addAbility) { AddAbility(abilityName, true); } else { RemoveTimer('Mutagen14Timer'); } } public final function FailFundamentalsFirstAchievementCondition() { SetFailedFundamentalsFirstAchievementCondition(true); } public final function SetUsedQuenInCombat() { usedQuenInCombat = true; } public final function UsedQuenInCombat() : bool { return usedQuenInCombat; } event OnCombatStart() { var quenEntity, glyphQuen : W3QuenEntity; var focus, stamina : float; var glowTargets, moTargets, actors : array< CActor >; var delays : array< float >; var rand, i : int; var isHostile, isAlive, isUnconscious : bool; super.OnCombatStart(); if ( IsInCombatActionFriendly() ) { SetBIsCombatActionAllowed(true); SetBIsInputAllowed(true, 'OnCombatActionStart' ); } if(HasBuff(EET_Mutagen14)) { AddTimer('Mutagen14Timer', 2, true); } if(HasBuff(EET_Mutagen15)) { AddAbility(GetBuff(EET_Mutagen15).GetAbilityName(), false); } mutation12IsOnCooldown = false; quenEntity = (W3QuenEntity)signs[ST_Quen].entity; if(quenEntity) { usedQuenInCombat = quenEntity.IsAnyQuenActive(); } else { usedQuenInCombat = false; } if(usedQuenInCombat || HasPotionBuff() || IsEquippedSwordUpgradedWithOil(true) || IsEquippedSwordUpgradedWithOil(false)) { SetFailedFundamentalsFirstAchievementCondition(true); } else { if(IsAnyItemEquippedOnSlot(EES_PotionMutagen1) || IsAnyItemEquippedOnSlot(EES_PotionMutagen2) || IsAnyItemEquippedOnSlot(EES_PotionMutagen3) || IsAnyItemEquippedOnSlot(EES_PotionMutagen4)) SetFailedFundamentalsFirstAchievementCondition(true); else SetFailedFundamentalsFirstAchievementCondition(false); } if(CanUseSkill(S_Sword_s20) && IsThreatened()) { focus = GetStat(BCS_Focus); if(focus < 1) { GainStat(BCS_Focus, 1 - focus); } } if ( HasAbility('Glyphword 17 _Stats', true) && RandF() < CalculateAttributeValue(GetAttributeValue('quen_apply_chance')) ) { stamina = GetStat(BCS_Stamina); glyphQuen = (W3QuenEntity)theGame.CreateEntity( signs[ST_Quen].template, GetWorldPosition(), GetWorldRotation() ); glyphQuen.Init( signOwner, signs[ST_Quen].entity, true ); glyphQuen.OnStarted(); glyphQuen.OnThrowing(); glyphQuen.OnEnded(); ForceSetStat(BCS_Stamina, stamina); } MeditationForceAbort(true); if( IsMutationActive( EPMT_Mutation4 ) ) { AddEffectDefault( EET_Mutation4, this, "combat start", false ); } if( IsMutationActive( EPMT_Mutation5 ) && GetStat( BCS_Focus ) >= 1.f ) //zur13 modSSS { AddEffectDefault( EET_Mutation5, this, "", false ); } if( IsMutationActive( EPMT_Mutation7 ) ) //zur13 modSSS { RemoveTimer( 'Mutation7CombatStartHackFixGo' ); AddTimer( 'Mutation7CombatStartHackFix', 1.f, true, , , , true ); } if( IsMutationActive( EPMT_Mutation8 ) ) //zur13 modSSS { theGame.MutationHUDFeedback( MFT_PlayRepeat ); } if( IsMutationActive( EPMT_Mutation10 ) ) //zur13 modSSS { PlayEffect( 'mutation_10' ); PlayEffect( 'critical_toxicity' ); AddTimer( 'Mutation10StopEffect', 5.f ); } } timer function Mutation7CombatStartHackFix( dt : float, id : int ) { var actors : array< CActor >; actors = GetEnemies(); if( actors.Size() > 0 ) { AddTimer( 'Mutation7CombatStartHackFixGo', 0.5f ); RemoveTimer( 'Mutation7CombatStartHackFix' ); } } timer function Mutation7CombatStartHackFixGo( dt : float, id : int ) { var actors : array< CActor >; if( IsMutationActive( EPMT_Mutation7 ) ) { actors = GetEnemies(); if( actors.Size() > 1 ) { AddEffectDefault( EET_Mutation7Buff, this, "Mutation 7, combat start" ); } } } public final function IsInFistFight() : bool { var enemies : array< CActor >; var i, j : int; var invent : CInventoryComponent; var weapons : array< SItemUniqueId >; if( IsInFistFightMiniGame() ) { return true; } enemies = GetEnemies(); for( i=0; i { weapons.Clear(); invent = enemies[i].GetInventory(); weapons = invent.GetHeldWeapons(); for( j=0; j { if( invent.IsItemFists( weapons[j] ) ) { return true; } } } return false; } timer function Mutation10StopEffect( dt : float, id : int ) { StopEffect( 'critical_toxicity' ); } event OnCombatFinished() { var mut17 : W3Mutagen17_Effect; var inGameConfigWrapper : CInGameConfigWrapper; var disableAutoSheathe : bool; super.OnCombatFinished(); if(HasBuff(EET_Mutagen10)) { RemoveAbilityAll( GetBuff(EET_Mutagen10).GetAbilityName() ); } if(HasBuff(EET_Mutagen14)) { RemoveAbilityAll( GetBuff(EET_Mutagen14).GetAbilityName() ); } if(HasBuff(EET_Mutagen15)) { RemoveAbilityAll( GetBuff(EET_Mutagen15).GetAbilityName() ); } if(HasBuff(EET_Mutagen17)) { mut17 = (W3Mutagen17_Effect)GetBuff(EET_Mutagen17); mut17.ClearBoost(); } if(HasBuff(EET_Mutagen18)) { RemoveAbilityAll( GetBuff(EET_Mutagen18).GetAbilityName() ); } if(HasBuff(EET_Mutagen22)) { RemoveAbilityAll( GetBuff(EET_Mutagen22).GetAbilityName() ); } if(HasBuff(EET_Mutagen27)) { RemoveAbilityAll( GetBuff(EET_Mutagen27).GetAbilityName() ); } RemoveBuff( EET_Mutation3 ); RemoveBuff( EET_Mutation4 ); RemoveBuff( EET_Mutation5 ); RemoveBuff( EET_Mutation7Buff ); RemoveBuff( EET_Mutation7Debuff ); if( IsMutationActive( EPMT_Mutation7 ) ) { theGame.MutationHUDFeedback( MFT_PlayHide ); } if( IsMutationActive( EPMT_Mutation8 ) ) //zur13 modSSS { theGame.MutationHUDFeedback( MFT_PlayHide ); } RemoveBuff( EET_Mutation10 ); RemoveBuff( EET_LynxSetBonus ); if(GetStat(BCS_Focus) > 0) { AddTimer('DelayedAdrenalineDrain', theGame.params.ADRENALINE_DRAIN_AFTER_COMBAT_DELAY, , , , true); } thePlayer.abilityManager.ResetOverhealBonus(); usedQuenInCombat = false; theGame.GetGamerProfile().ResetStat(ES_FinesseKills); LogChannel( 'OnCombatFinished', "OnCombatFinished: DelayedSheathSword timer added" ); inGameConfigWrapper = (CInGameConfigWrapper)theGame.GetInGameConfigWrapper(); disableAutoSheathe = inGameConfigWrapper.GetVarValue( 'Gameplay', 'DisableAutomaticSwordSheathe' ); if( !disableAutoSheathe ) { if ( ShouldAutoSheathSwordInstantly() ) AddTimer( 'DelayedSheathSword', 0.5f ); else AddTimer( 'DelayedSheathSword', 2.f ); } OnBlockAllCombatTickets( false ); runewordInfusionType = ST_None; } public function PlayHitEffect( damageAction : W3DamageAction ) { var hitReactionType : EHitReactionType; var isAtBack : bool; if( damageAction.GetMutation4Triggered() ) { hitReactionType = damageAction.GetHitReactionType(); isAtBack = IsAttackerAtBack( damageAction.attacker ); if( hitReactionType != EHRT_Heavy ) { if( isAtBack ) { damageAction.SetHitEffect( 'light_hit_back_toxic', true ); } else { damageAction.SetHitEffect( 'light_hit_toxic' ); } } else { if( isAtBack ) { damageAction.SetHitEffect( 'heavy_hit_back_toxic' ,true ); } else { damageAction.SetHitEffect( 'heavy_hit_toxic' ); } } } super.PlayHitEffect( damageAction ); } timer function DelayedAdrenalineDrain(dt : float, id : int) { if ( !HasBuff(EET_Runeword8) ) AddEffectDefault(EET_AdrenalineDrain, this, "after_combat_adrenaline_drain"); } protected function Attack( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array, attackAnimationName : name, hitTime : float, weaponEntity : CItemEntity) { var mutagen17 : W3Mutagen17_Effect; super.Attack(hitTarget, animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime, weaponEntity); if( (CActor)hitTarget && HasBuff(EET_Mutagen17) ) { mutagen17 = (W3Mutagen17_Effect)GetBuff(EET_Mutagen17); if(mutagen17.HasBoost()) { mutagen17.ClearBoost(); } } } public final timer function SpecialAttackLightSustainCost(dt : float, id : int) { var focusPerSec, cost, delay : float; var reduction : SAbilityAttributeValue; var skillLevel : int; if(abilityManager && abilityManager.IsInitialized() && IsAlive()) { PauseStaminaRegen('WhirlSkill'); if(GetStat(BCS_Stamina) > 0) { cost = GetStaminaActionCost(ESAT_Ability, GetSkillAbilityName(S_Sword_s01), dt); delay = GetStaminaActionDelay(ESAT_Ability, GetSkillAbilityName(S_Sword_s01), dt); skillLevel = GetSkillLevel(S_Sword_s01); if(skillLevel > 1) { reduction = GetSkillAttributeValue(S_Sword_s01, 'cost_reduction', false, true) * (skillLevel - 1); cost = MaxF(0, cost * (1 - reduction.valueMultiplicative) - reduction.valueAdditive); } DrainStamina(ESAT_FixedValue, cost, delay, GetSkillAbilityName(S_Sword_s01)); } else { GetSkillAttributeValue(S_Sword_s01, 'focus_cost_per_sec', false, true); focusPerSec = GetWhirlFocusCostPerSec(); DrainFocus(focusPerSec * dt); } } if(GetStat(BCS_Stamina) <= 0 && GetStat(BCS_Focus) <= 0) { OnPerformSpecialAttack(true, false); } } public final function GetWhirlFocusCostPerSec() : float { var ability : SAbilityAttributeValue; var val : float; var skillLevel : int; ability = GetSkillAttributeValue(S_Sword_s01, 'focus_cost_per_sec_initial', false, false); skillLevel = GetSkillLevel(S_Sword_s01); if(skillLevel > 1) ability -= GetSkillAttributeValue(S_Sword_s01, 'cost_reduction', false, false) * (skillLevel-1); val = CalculateAttributeValue(ability); return val; } public final timer function SpecialAttackHeavySustainCost(dt : float, id : int) { var focusHighlight, ratio : float; var hud : CR4ScriptedHud; var hudWolfHeadModule : CR4HudModuleWolfHead; DrainStamina(ESAT_Ability, 0, 0, GetSkillAbilityName(S_Sword_s02), dt); if(GetStat(BCS_Stamina) <= 0) OnPerformSpecialAttack(false, false); ratio = EngineTimeToFloat(theGame.GetEngineTime() - specialHeavyStartEngineTime) / specialHeavyChargeDuration; if(ratio > 0.95) ratio = 1; SetSpecialAttackTimeRatio(ratio); focusHighlight = ratio * GetStatMax(BCS_Focus); focusHighlight = MinF(focusHighlight, GetStat(BCS_Focus)); focusHighlight = FloorF(focusHighlight); hud = (CR4ScriptedHud)theGame.GetHud(); if ( hud ) { hudWolfHeadModule = (CR4HudModuleWolfHead)hud.GetHudModule( "WolfHeadModule" ); if ( hudWolfHeadModule ) { hudWolfHeadModule.LockFocusPoints((int)focusHighlight); } } } public function OnSpecialAttackHeavyActionProcess() { var hud : CR4ScriptedHud; var hudWolfHeadModule : CR4HudModuleWolfHead; super.OnSpecialAttackHeavyActionProcess(); hud = (CR4ScriptedHud)theGame.GetHud(); if ( hud ) { hudWolfHeadModule = (CR4HudModuleWolfHead)hud.GetHudModule( "WolfHeadModule" ); if ( hudWolfHeadModule ) { hudWolfHeadModule.ResetFocusPoints(); } } } timer function IsSpecialLightAttackInputHeld ( time : float, id : int ) { var hasResource : bool; if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' ) { if ( GetBIsCombatActionAllowed() && inputHandler.IsActionAllowed(EIAB_SwordAttack)) { if(GetStat(BCS_Stamina) > 0) { hasResource = true; } else { hasResource = (GetStat(BCS_Focus) >= GetWhirlFocusCostPerSec() * time); } if(hasResource) { SetupCombatAction( EBAT_SpecialAttack_Light, BS_Pressed ); RemoveTimer('IsSpecialLightAttackInputHeld'); } else if(!playedSpecialAttackMissingResourceSound) { IndicateTooLowAdrenaline(); playedSpecialAttackMissingResourceSound = true; } } } else { RemoveTimer('IsSpecialLightAttackInputHeld'); } } timer function IsSpecialHeavyAttackInputHeld ( time : float, id : int ) { var cost : float; if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' ) { cost = CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s02, 'stamina_cost_per_sec', false, false)); if( GetBIsCombatActionAllowed() && inputHandler.IsActionAllowed(EIAB_SwordAttack)) { if(GetStat(BCS_Stamina) >= cost) { SetupCombatAction( EBAT_SpecialAttack_Heavy, BS_Pressed ); RemoveTimer('IsSpecialHeavyAttackInputHeld'); } else if(!playedSpecialAttackMissingResourceSound) { IndicateTooLowAdrenaline(); playedSpecialAttackMissingResourceSound = true; } } } else { RemoveTimer('IsSpecialHeavyAttackInputHeld'); } } public function EvadePressed( bufferAction : EBufferActionType ) { var cat : float; if( (bufferAction == EBAT_Dodge && IsActionAllowed(EIAB_Dodge)) || (bufferAction == EBAT_Roll && IsActionAllowed(EIAB_Roll)) ) { if(bufferAction != EBAT_Roll && ShouldProcessTutorial('TutorialDodge')) { FactsAdd("tut_in_dodge", 1, 2); if(FactsQuerySum("tut_fight_use_slomo") > 0) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) ); FactsRemove("tut_fight_slomo_ON"); } } else if(bufferAction == EBAT_Roll && ShouldProcessTutorial('TutorialRoll')) { FactsAdd("tut_in_roll", 1, 2); if(FactsQuerySum("tut_fight_use_slomo") > 0) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) ); FactsRemove("tut_fight_slomo_ON"); } } if ( GetBIsInputAllowed() ) { if ( GetBIsCombatActionAllowed() ) { CriticalEffectAnimationInterrupted("Dodge 2"); PushCombatActionOnBuffer( bufferAction, BS_Released ); ProcessCombatActionBuffer(); } else if ( IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) { if ( CanPlayHitAnim() && IsThreatened() ) { CriticalEffectAnimationInterrupted("Dodge 1"); PushCombatActionOnBuffer( bufferAction, BS_Released ); ProcessCombatActionBuffer(); } else PushCombatActionOnBuffer( bufferAction, BS_Released ); } else if ( !( IsCurrentSignChanneled() ) ) { PushCombatActionOnBuffer( bufferAction, BS_Released ); } } else { if ( IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) { if ( CanPlayHitAnim() && IsThreatened() ) { CriticalEffectAnimationInterrupted("Dodge 3"); PushCombatActionOnBuffer( bufferAction, BS_Released ); ProcessCombatActionBuffer(); } else PushCombatActionOnBuffer( bufferAction, BS_Released ); } LogChannel( 'InputNotAllowed', "InputNotAllowed" ); } } else { DisplayActionDisallowedHudMessage(EIAB_Dodge); } } public function ProcessCombatActionBuffer() : bool { var action : EBufferActionType = this.BufferCombatAction; var stage : EButtonStage = this.BufferButtonStage; var throwStage : EThrowStage; var actionResult : bool = true; if( isInFinisher ) { return false; } if ( action != EBAT_SpecialAttack_Heavy ) specialAttackCamera = false; if(super.ProcessCombatActionBuffer()) return true; switch ( action ) { case EBAT_CastSign : { switch ( stage ) { case BS_Pressed : { actionResult = this.CastSign(); LogChannel('SignDebug', "CastSign()"); } break; default : { actionResult = false; } break; } } break; case EBAT_SpecialAttack_Light : { switch ( stage ) { case BS_Pressed : { actionResult = this.OnPerformSpecialAttack( true, true ); } break; case BS_Released : { actionResult = this.OnPerformSpecialAttack( true, false ); } break; default : { actionResult = false; } break; } } break; case EBAT_SpecialAttack_Heavy : { switch ( stage ) { case BS_Pressed : { actionResult = this.OnPerformSpecialAttack( false, true ); } break; case BS_Released : { actionResult = this.OnPerformSpecialAttack( false, false ); } break; default : { actionResult = false; } break; } } break; default: return false; } this.CleanCombatActionBuffer(); if (actionResult) { SetCombatAction( action ) ; } return true; } event OnPerformSpecialAttack( isLightAttack : bool, enableAttack : bool ){} public final function GetEnemies() : array< CActor > { var actors, actors2 : array; var i : int; actors = GetWitcherPlayer().GetHostileEnemies(); ArrayOfActorsAppendUnique( actors, GetWitcherPlayer().GetMoveTargets() ); thePlayer.GetVisibleEnemies( actors2 ); ArrayOfActorsAppendUnique( actors, actors2 ); for( i=actors.Size()-1; i>=0; i-=1 ) { if( !IsRequiredAttitudeBetween( actors[i], this, true ) ) { actors.EraseFast( i ); } } return actors; } event OnPlayerTickTimer( deltaTime : float ) { super.OnPlayerTickTimer( deltaTime ); if ( !IsInCombat() ) { fastAttackCounter = 0; heavyAttackCounter = 0; } WmkGetMapMenuInstance().OnTick(deltaTime); // -= WMK:modAQOOM =- } protected function PrepareAttackAction( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array, attackAnimationName : name, hitTime : float, weaponEntity : CItemEntity, out attackAction : W3Action_Attack) : bool { var ret : bool; var skill : ESkill; ret = super.PrepareAttackAction(hitTarget, animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime, weaponEntity, attackAction); if(!ret) return false; if(attackAction.IsActionMelee()) { skill = SkillNameToEnum( attackAction.GetAttackTypeName() ); if( skill != S_SUndefined && CanUseSkill(skill)) { if(IsLightAttack(animData.attackName)) fastAttackCounter += 1; else fastAttackCounter = 0; if(IsHeavyAttack(animData.attackName)) heavyAttackCounter += 1; else heavyAttackCounter = 0; } } AddTimer('FastAttackCounterDecay',5.0); AddTimer('HeavyAttackCounterDecay',5.0); return true; } protected function TestParryAndCounter(data : CPreAttackEventData, weaponId : SItemUniqueId, out parried : bool, out countered : bool) : array { if(SkillNameToEnum(attackActionName) == S_Sword_s02) data.Can_Parry_Attack = false; return super.TestParryAndCounter(data, weaponId, parried, countered); } private timer function FastAttackCounterDecay(delta : float, id : int) { fastAttackCounter = 0; } private timer function HeavyAttackCounterDecay(delta : float, id : int) { heavyAttackCounter = 0; } public function GetCraftingSchematicsNames() : array {return craftingSchematics;} public function RemoveAllCraftingSchematics() { craftingSchematics.Clear(); } function AddCraftingSchematic( nam : name, optional isSilent : bool, optional skipTutorialUpdate : bool ) : bool { var i : int; if(!skipTutorialUpdate && ShouldProcessTutorial('TutorialCraftingGotRecipe')) { FactsAdd("tut_received_schematic"); } for(i=0; i { if(craftingSchematics[i] == nam) return false; if(StrCmp(craftingSchematics[i],nam) > 0) { craftingSchematics.Insert(i,nam); AddCraftingHudNotification( nam, isSilent ); theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_CraftingSchematics ); return true; } } craftingSchematics.PushBack(nam); AddCraftingHudNotification( nam, isSilent ); theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_CraftingSchematics ); return true; } function AddCraftingHudNotification( nam : name, isSilent : bool ) { var hud : CR4ScriptedHud; if( !isSilent ) { hud = (CR4ScriptedHud)theGame.GetHud(); if( hud ) { hud.OnCraftingSchematicUpdate( nam ); } } } function AddAlchemyHudNotification( nam : name, isSilent : bool ) { var hud : CR4ScriptedHud; if( !isSilent ) { hud = (CR4ScriptedHud)theGame.GetHud(); if( hud ) { hud.OnAlchemySchematicUpdate( nam ); } } } event OnMutation11Triggered() { var min, max : SAbilityAttributeValue; var healValue : float; var quenEntity : W3QuenEntity; if( IsSwimming() || IsDiving() || IsSailing() || IsUsingHorse() || IsUsingBoat() || IsUsingVehicle() || IsUsingExploration() ) { ForceSetStat( BCS_Vitality, GetStatMax( BCS_Vitality ) ); theGame.MutationHUDFeedback( MFT_PlayOnce ); GCameraShake( 1.0f, , , , true, 'camera_shake_loop_lvl1_1' ); AddTimer( 'StopMutation11CamShake', 2.f ); theGame.VibrateControllerVeryHard( 2.f ); Mutation11ShockWave( true ); AddEffectDefault( EET_Mutation11Debuff, NULL, "Mutation 11 Debuff", false ); } else { AddEffectDefault( EET_Mutation11Buff, this, "Mutation 11", false ); } } timer function StopMutation11CamShake( dt : float, id : int ) { theGame.GetGameCamera().StopAnimation( 'camera_shake_loop_lvl1_1' ); } private var mutation12IsOnCooldown : bool; public final function AddMutation12Decoction() { var params : SCustomEffectParams; var buffs : array< EEffectType >; var existingDecoctionBuffs : array; var i : int; var effectType : EEffectType; var decoctions : array< SItemUniqueId >; var tmpName : name; var min, max : SAbilityAttributeValue; if( mutation12IsOnCooldown ) { return; } existingDecoctionBuffs = GetDrunkMutagens( "Mutation12" ); theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation12', 'maxcap', min, max ); if( existingDecoctionBuffs.Size() >= min.valueAdditive ) { return; } mutation12IsOnCooldown = true; theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation12', 'cooldown', min, max ); AddTimer( 'Mutation12Cooldown', CalculateAttributeValue( min ) ); decoctions = inv.GetItemsByTag( 'Mutagen' ); for( i=decoctions.Size()-1; i>=0; i-=1 ) { inv.GetPotionItemBuffData( decoctions[i], effectType, tmpName ); if( HasBuff( effectType ) ) { decoctions.EraseFast( i ); continue; } buffs.PushBack( effectType ); } if( buffs.Size() == 0 ) { for( i=EET_Mutagen01; i<=EET_Mutagen28; i+=1 ) { if( !HasBuff( i ) ) { buffs.PushBack( i ); } } } buffs.Remove( EET_Mutagen16 ); buffs.Remove( EET_Mutagen24 ); if( buffs.Size() == 0 ) { return; } theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation12', 'duration', min, max ); params.effectType = buffs[ RandRange( buffs.Size() ) ]; params.creator = this; params.sourceName = "Mutation12"; params.duration = min.valueAdditive; AddEffectCustom( params ); ( ( W3Mutagen_Effect ) GetBuff( params.effectType, params.sourceName ) ).OverrideIcon( DecoctionEffectTypeToItemName( params.effectType ) ); if ( !IsEffectActive( 'invisible' ) ) { PlayEffect( 'use_potion' ); } theGame.MutationHUDFeedback( MFT_PlayOnce ); } timer function Mutation12Cooldown( dt : float, id : int ) { mutation12IsOnCooldown = false; } public final function HasResourcesToStartAnyMutationResearch() : bool { var greenPoints, redPoints, bluePoints, count : int; var itemIDs : array< SItemUniqueId >; if( levelManager.GetPointsFree( ESkillPoint ) > 0 ) { return true; } count = inv.GetItemQuantityByName( 'Greater mutagen green' ); if( count > 0 ) { itemIDs = inv.GetItemsByName( 'Greater mutagen green' ); greenPoints = inv.GetMutationResearchPoints( SC_Green, itemIDs[0] ); if( greenPoints > 0 ) { return true; } } count = inv.GetItemQuantityByName( 'Greater mutagen red' ); if( count > 0 ) { itemIDs.Clear(); itemIDs = inv.GetItemsByName( 'Greater mutagen red' ); redPoints = inv.GetMutationResearchPoints( SC_Red, itemIDs[0] ); if( redPoints > 0 ) { return true; } } count = inv.GetItemQuantityByName( 'Greater mutagen blue' ); if( count > 0 ) { itemIDs.Clear(); itemIDs = inv.GetItemsByName( 'Greater mutagen blue' ); bluePoints = inv.GetMutationResearchPoints( SC_Blue, itemIDs[0] ); if( bluePoints > 0 ) { return true; } } return false; } public final function Mutation11StartAnimation() { thePlayer.ActionPlaySlotAnimationAsync( 'PLAYER_SLOT', 'geralt_mutation_11', 0.2, 0.2 ); BlockAllActions( 'Mutation11', true ); loopingCameraShakeAnimName = 'camera_shake_loop_lvl1_1'; GCameraShake( 1.0f, , , , true, loopingCameraShakeAnimName ); theGame.VibrateControllerVeryHard( 15.f ); storedInteractionPriority = GetInteractionPriority(); SetInteractionPriority( IP_Max_Unpushable ); } event OnAnimEvent_Mutation11ShockWave( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { Mutation11ShockWave( false ); } private final function Mutation11ShockWave( skipQuenSign : bool ) { var action : W3DamageAction; var ents : array< CGameplayEntity >; var i, j : int; var damages : array< SRawDamage >; FindGameplayEntitiesInSphere(ents, GetWorldPosition(), 5.f, 1000, '', FLAG_OnlyAliveActors + FLAG_ExcludeTarget + FLAG_Attitude_Hostile + FLAG_Attitude_Neutral, this); if( ents.Size() > 0 ) { damages = theGame.GetDefinitionsManager().GetDamagesFromAbility( 'Mutation11' ); } for(i=0; i { action = new W3DamageAction in theGame; action.Initialize( this, ents[i], NULL, "Mutation11", EHRT_Heavy, CPS_SpellPower, false, false, true, false ); for( j=0; j { action.AddDamage( damages[j].dmgType, damages[j].dmgVal ); } action.SetCannotReturnDamage( true ); action.SetProcessBuffsIfNoDamage( true ); action.AddEffectInfo( EET_KnockdownTypeApplicator ); action.SetHitAnimationPlayType( EAHA_ForceYes ); action.SetCanPlayHitParticle( false ); theGame.damageMgr.ProcessAction( action ); delete action; } mutation11QuenEntity = ( W3QuenEntity )GetSignEntity( ST_Quen ); if( !mutation11QuenEntity ) { mutation11QuenEntity = (W3QuenEntity)theGame.CreateEntity( GetSignTemplate( ST_Quen ), GetWorldPosition(), GetWorldRotation() ); mutation11QuenEntity.CreateAttachment( this, 'quen_sphere' ); AddTimer( 'DestroyMutation11QuenEntity', 2.f ); } mutation11QuenEntity.PlayHitEffect( 'quen_impulse_explode', mutation11QuenEntity.GetWorldRotation() ); if( !skipQuenSign ) { PlayEffect( 'mutation_11_second_life' ); RestoreQuen( 1000000.f, 10.f, true ); } } private var mutation11QuenEntity : W3QuenEntity; private var storedInteractionPriority : EInteractionPriority; timer function DestroyMutation11QuenEntity( dt : float, id : int ) { if( mutation11QuenEntity ) { mutation11QuenEntity.Destroy(); } } event OnAnimEvent_Mutation11AnimEnd( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if( animEventType == AET_DurationEnd ) { BlockAllActions( 'Mutation11', false ); theGame.GetGameCamera().StopAnimation( 'camera_shake_loop_lvl1_1' ); theGame.StopVibrateController(); SetInteractionPriority( storedInteractionPriority ); RemoveBuff( EET_Mutation11Buff, true ); } else if ( animEventType == AET_DurationStart || animEventType == AET_DurationStartInTheMiddle ) { SetBehaviorVariable( 'AIControlled', 0.f ); } } public final function MutationSystemEnable( enable : bool ) { ( ( W3PlayerAbilityManager ) abilityManager ).MutationSystemEnable( enable ); } public final function IsMutationSystemEnabled() : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).IsMutationSystemEnabled(); } public final function GetMutation( mutationType : EPlayerMutationType ) : SMutation { return ( ( W3PlayerAbilityManager ) abilityManager ).GetMutation( mutationType ); } public final function IsMutationActive( mutationType : EPlayerMutationType) : bool { var swordQuality : int; var sword : SItemUniqueId; if( !SSS_IsMutationEquipped( mutationType, GetEquippedMutationType() ) ) //zur13 modSSS { return false; } switch( mutationType ) { case EPMT_Mutation4 : case EPMT_Mutation5 : case EPMT_Mutation7 : case EPMT_Mutation8 : case EPMT_Mutation10 : case EPMT_Mutation11 : case EPMT_Mutation12 : if( IsInFistFight() ) { return false; } } if( mutationType == EPMT_Mutation1 ) { sword = inv.GetCurrentlyHeldSword(); swordQuality = inv.GetItemQuality( sword ); if( swordQuality < 3 ) { return false; } } return true; } public final function SetEquippedMutation( mutationType : EPlayerMutationType ) : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).SetEquippedMutation( mutationType ); } public final function GetEquippedMutationType() : array< EPlayerMutationType > //zur13 modSSS { return ( ( W3PlayerAbilityManager ) abilityManager ).GetEquippedMutationType(); } public final function CanEquipMutation(mutationType : EPlayerMutationType) : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).CanEquipMutation( mutationType ); } public final function CanResearchMutation( mutationType : EPlayerMutationType ) : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).CanResearchMutation( mutationType ); } public final function IsMutationResearched(mutationType : EPlayerMutationType) : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).IsMutationResearched( mutationType ); } public final function GetMutationResearchProgress(mutationType : EPlayerMutationType) : int { return ( ( W3PlayerAbilityManager ) abilityManager ).GetMutationResearchProgress( mutationType ); } public final function GetMasterMutationStage() : int { return ( ( W3PlayerAbilityManager ) abilityManager ).GetMasterMutationStage(); } public final function MutationResearchWithSkillPoints(mutation : EPlayerMutationType, skillPoints : int) : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).MutationResearchWithSkillPoints( mutation, skillPoints ); } public final function MutationResearchWithItem(mutation : EPlayerMutationType, item : SItemUniqueId) : bool { return ( ( W3PlayerAbilityManager ) abilityManager ).MutationResearchWithItem( mutation, item ); } public final function GetMutationLocalizedName( mutationType : EPlayerMutationType ) : string { var pam : W3PlayerAbilityManager; var locKey : name; pam = (W3PlayerAbilityManager)GetWitcherPlayer().abilityManager; locKey = pam.GetMutationNameLocalizationKey( mutationType ); return GetLocStringByKeyExt( locKey ); } public final function GetMutationLocalizedDescription( mutationType : EPlayerMutationType ) : string { var pam : W3PlayerAbilityManager; var locKey : name; var arrStr : array< string >; var dm : CDefinitionsManagerAccessor; var min, max, sp : SAbilityAttributeValue; var tmp, tmp2, tox, critBonusDamage, val : float; var stats, stats2 : SPlayerOffenseStats; var buffPerc, exampleEnemyCount, debuffPerc : int; pam = (W3PlayerAbilityManager)GetWitcherPlayer().abilityManager; locKey = pam.GetMutationDescriptionLocalizationKey( mutationType ); dm = theGame.GetDefinitionsManager(); switch( mutationType ) { case EPMT_Mutation1 : dm.GetAbilityAttributeValue('Mutation1', 'dmg_bonus_factor', min, max); arrStr.PushBack( NoTrailZeros( RoundMath( 100 * min.valueAdditive ) ) ); break; case EPMT_Mutation2 : sp = GetPowerStatValue( CPS_SpellPower ); dm.GetAbilityAttributeValue( 'Mutation2', 'crit_chance_factor', min, max ); arrStr.PushBack( NoTrailZeros( RoundMath( 100 * ( min.valueAdditive + sp.valueMultiplicative * min.valueMultiplicative ) ) ) ); dm.GetAbilityAttributeValue( 'Mutation2', 'crit_damage_factor', min, max ); critBonusDamage = sp.valueMultiplicative * min.valueMultiplicative; arrStr.PushBack( NoTrailZeros( RoundMath( 100 * critBonusDamage ) ) ); break; case EPMT_Mutation3 : dm.GetAbilityAttributeValue( 'Mutation3', 'attack_power', min, max ); tmp = min.valueMultiplicative; arrStr.PushBack( NoTrailZeros( RoundMath( 100 * tmp ) ) ); dm.GetAbilityAttributeValue( 'Mutation3', 'maxcap', min, max ); arrStr.PushBack( NoTrailZeros( RoundMath( 100 * tmp * min.valueAdditive ) ) ); break; case EPMT_Mutation4 : dm.GetAbilityAttributeValue( 'AcidEffect', 'DirectDamage', min, max ); tmp2 = 100 * min.valueAdditive; dm.GetAbilityAttributeValue( 'AcidEffect', 'duration', min, max ); tmp2 *= min.valueAdditive; arrStr.PushBack( NoTrailZeros( tmp2 ) ); tox = GetStat( BCS_Toxicity ); if( tox > 0 ) { tmp = RoundMath( tmp2 * tox ); } else { tmp = tmp2; } arrStr.PushBack( NoTrailZeros( tmp ) ); tox = GetStatMax( BCS_Toxicity ); tmp = RoundMath( tmp2 * tox ); arrStr.PushBack( NoTrailZeros( tmp ) ); break; case EPMT_Mutation5 : dm.GetAbilityAttributeValue( 'Mutation5', 'mut5_dmg_red_perc', min, max ); tmp = min.valueAdditive; arrStr.PushBack( NoTrailZeros( 100 * tmp ) ); arrStr.PushBack( NoTrailZeros( 100 * tmp * 3 ) ); break; case EPMT_Mutation6 : theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation6', 'full_freeze_chance', min, max ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative ) ); theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation6', 'ForceDamage', min, max ); sp = GetTotalSignSpellPower( S_Magic_1 ); val = sp.valueAdditive + sp.valueMultiplicative * ( sp.valueBase + min.valueAdditive ); arrStr.PushBack( NoTrailZeros( RoundMath( val ) ) ); break; case EPMT_Mutation7 : dm.GetAbilityAttributeValue( 'Mutation7Buff', 'attack_power', min, max ); buffPerc = (int) ( 100 * min.valueMultiplicative ); arrStr.PushBack( NoTrailZeros( buffPerc ) ); dm.GetAbilityAttributeValue( 'Mutation7BuffEffect', 'duration', min, max ); arrStr.PushBack( NoTrailZeros( min.valueAdditive ) ); exampleEnemyCount = 11; arrStr.PushBack( exampleEnemyCount ); arrStr.PushBack( buffPerc * ( exampleEnemyCount -1 ) ); dm.GetAbilityAttributeValue( 'Mutation7Debuff', 'attack_power', min, max ); debuffPerc = (int) ( - 100 * min.valueMultiplicative ); arrStr.PushBack( NoTrailZeros( debuffPerc ) ); theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation7Debuff', 'minCapStacks', min, max ); arrStr.PushBack( NoTrailZeros( debuffPerc * min.valueAdditive ) ); dm.GetAbilityAttributeValue( 'Mutation7DebuffEffect', 'duration', min, max ); arrStr.PushBack( NoTrailZeros( min.valueAdditive ) ); break; case EPMT_Mutation8 : dm.GetAbilityAttributeValue( 'Mutation8', 'dmg_bonus', min, max ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative ) ); dm.GetAbilityAttributeValue( 'Mutation8', 'hp_perc_trigger', min, max ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative ) ); break; case EPMT_Mutation9 : stats = GetOffenseStatsList( 1 ); arrStr.PushBack( NoTrailZeros( RoundMath( stats.crossbowSteelDmg ) ) ); stats2 = GetOffenseStatsList( 2 ); arrStr.PushBack( NoTrailZeros( RoundMath( stats2.crossbowSteelDmg ) ) ); dm.GetAbilityAttributeValue( 'Mutation9', 'critical_hit_chance', min, max ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative ) ); dm.GetAbilityAttributeValue( 'Mutation9', 'health_reduction', min, max ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative ) ); break; case EPMT_Mutation10 : dm.GetAbilityAttributeValue( 'Mutation10Effect', 'mutation10_stat_boost', min, max ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative ) ); arrStr.PushBack( NoTrailZeros( 100 * min.valueMultiplicative * GetStatMax( BCS_Toxicity ) ) ); break; case EPMT_Mutation11 : arrStr.PushBack( 100 ); dm.GetAbilityAttributeValue( 'Mutation11DebuffEffect', 'duration', min, max); arrStr.PushBack( NoTrailZeros( min.valueAdditive ) ); break; case EPMT_Mutation12 : dm.GetAbilityAttributeValue( 'Mutation12', 'duration', min, max ); arrStr.PushBack( NoTrailZeros( min.valueAdditive ) ); dm.GetAbilityAttributeValue( 'Mutation12', 'maxcap', min, max ); arrStr.PushBack( NoTrailZeros( min.valueAdditive ) ); break; case EPMT_MutationMaster : arrStr.PushBack( "4" ); break; } return GetLocStringByKeyExtWithParams( locKey, , , arrStr ); } public final function ApplyMutation10StatBoost( out statValue : SAbilityAttributeValue ) { var attValue : SAbilityAttributeValue; var currToxicity : float; if( IsMutationActive( EPMT_Mutation10 ) ) { currToxicity = GetStat( BCS_Toxicity ); if( currToxicity > 0.f ) { attValue = GetAttributeValue( 'mutation10_stat_boost' ); currToxicity *= attValue.valueMultiplicative; statValue.valueMultiplicative += currToxicity; } } } public final function IsBookRead( bookName : name ):bool { return booksRead.Contains( bookName ); } public final function AddReadBook( bookName : name ):void { if( !booksRead.Contains( bookName ) ) { booksRead.PushBack( bookName ); } } public final function RemoveReadBook( bookName : name ):void { var idx : int = booksRead.FindFirst( bookName ); if( idx > -1 ) { booksRead.Erase( idx ); } } public final function GetMutagenBuffs() : array< W3Mutagen_Effect > { var null : array< W3Mutagen_Effect >; if(effectManager) { return effectManager.GetMutagenBuffs(); } return null; } public function GetAlchemyRecipes() : array { return alchemyRecipes; } public function CanLearnAlchemyRecipe(recipeName : name) : bool { var dm : CDefinitionsManagerAccessor; var recipeNode : SCustomNode; var i, tmpInt : int; var tmpName : name; dm = theGame.GetDefinitionsManager(); if ( dm.GetSubNodeByAttributeValueAsCName( recipeNode, 'alchemy_recipes', 'name_name', recipeName ) ) { return true; } return false; } private final function RemoveAlchemyRecipe(recipeName : name) { alchemyRecipes.Remove(recipeName); } private final function RemoveAllAlchemyRecipes() { alchemyRecipes.Clear(); } function AddAlchemyRecipe(nam : name, optional isSilent : bool, optional skipTutorialUpdate : bool) : bool { var i, potions, bombs : int; var found : bool; var m_alchemyManager : W3AlchemyManager; var recipe : SAlchemyRecipe; var knownBombTypes : array; var strRecipeName, recipeNameWithoutLevel : string; if(!IsAlchemyRecipe(nam)) return false; found = false; for(i=0; i { if(alchemyRecipes[i] == nam) return false; if(StrCmp(alchemyRecipes[i],nam) > 0) { alchemyRecipes.Insert(i,nam); found = true; AddAlchemyHudNotification(nam,isSilent); break; } } if(!found) { alchemyRecipes.PushBack(nam); AddAlchemyHudNotification(nam,isSilent); } m_alchemyManager = new W3AlchemyManager in this; m_alchemyManager.Init(alchemyRecipes); m_alchemyManager.GetRecipe(nam, recipe); if(CanUseSkill(S_Alchemy_s18)) { if ((recipe.cookedItemType != EACIT_Bolt) && (recipe.cookedItemType != EACIT_Undefined) && (recipe.level <= GetSkillLevel(S_Alchemy_s18))) AddAbility(SkillEnumToName(S_Alchemy_s18), true); } if(recipe.cookedItemType == EACIT_Bomb) { bombs = 0; for(i=0; i { m_alchemyManager.GetRecipe(alchemyRecipes[i], recipe); if(recipe.cookedItemType == EACIT_Bomb) { strRecipeName = NameToString(alchemyRecipes[i]); recipeNameWithoutLevel = StrLeft(strRecipeName, StrLen(strRecipeName)-2); if(!knownBombTypes.Contains(recipeNameWithoutLevel)) { bombs += 1; knownBombTypes.PushBack(recipeNameWithoutLevel); } } } theGame.GetGamerProfile().SetStat(ES_KnownBombRecipes, bombs); } else if(recipe.cookedItemType == EACIT_Potion || recipe.cookedItemType == EACIT_MutagenPotion || recipe.cookedItemType == EACIT_Alcohol || recipe.cookedItemType == EACIT_Quest) { potions = 0; for(i=0; i { m_alchemyManager.GetRecipe(alchemyRecipes[i], recipe); if(recipe.cookedItemType == EACIT_Potion || recipe.cookedItemType == EACIT_MutagenPotion || recipe.cookedItemType == EACIT_Alcohol || recipe.cookedItemType == EACIT_Quest) { potions += 1; } } theGame.GetGamerProfile().SetStat(ES_KnownPotionRecipes, potions); } theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_AlchemyRecipe ); return true; } public function GetDisplayHeavyAttackIndicator() : bool { return bDispalyHeavyAttackIndicator; } public function SetDisplayHeavyAttackIndicator( val : bool ) { bDispalyHeavyAttackIndicator = val; } public function GetDisplayHeavyAttackFirstLevelTimer() : bool { return bDisplayHeavyAttackFirstLevelTimer; } public function SetDisplayHeavyAttackFirstLevelTimer( val : bool ) { bDisplayHeavyAttackFirstLevelTimer = val; } public function SelectQuickslotItem( slot : EEquipmentSlots ) { var item : SItemUniqueId; GetItemEquippedOnSlot(slot, item); selectedItemId = item; } public function GetMedallion() : W3MedallionController { if ( !medallionController ) { medallionController = new W3MedallionController in this; } return medallionController; } public final function HighlightObjects(range : float, optional highlightTime : float ) { var ents : array; var i : int; FindGameplayEntitiesInSphere(ents, GetWorldPosition(), range, 100, 'HighlightedByMedalionFX', FLAG_ExcludePlayer); if(highlightTime == 0) highlightTime = 30; for(i=0; i { if(!ents[i].IsHighlighted()) { ents[i].SetHighlighted( true ); ents[i].PlayEffectSingle( 'medalion_detection_fx' ); ents[i].AddTimer( 'MedallionEffectOff', highlightTime ); } } } public final function HighlightEnemies(range : float, optional highlightTime : float ) { var ents : array; var i : int; var catComponent : CGameplayEffectsComponent; FindGameplayEntitiesInSphere(ents, GetWorldPosition(), range, 100, , FLAG_ExcludePlayer + FLAG_OnlyAliveActors); if(highlightTime == 0) highlightTime = 5; for(i=0; i { if(IsRequiredAttitudeBetween(this, ents[i], true)) { catComponent = GetGameplayEffectsComponent(ents[i]); if(catComponent) { catComponent.SetGameplayEffectFlag(EGEF_CatViewHiglight, true); ents[i].AddTimer( 'EnemyHighlightOff', highlightTime, , , , , true ); } } } } function SpawnMedallionEntity() { var rot : EulerAngles; var spawnedMedallion : CEntity; spawnedMedallion = theGame.GetEntityByTag( 'new_Witcher_medallion_FX' ); if ( !spawnedMedallion ) theGame.CreateEntity( medallionEntity, GetWorldPosition(), rot, true, false ); } public final function InterruptCombatFocusMode() { if( this.GetCurrentStateName() == 'CombatFocusMode_SelectSpot' ) { SetCanPlayHitAnim( true ); PopState(); } } public final function IsInDarkPlace() : bool { var envs : array< string >; if( FactsQuerySum( "tut_in_dark_place" ) ) { return true; } GetActiveAreaEnvironmentDefinitions( envs ); if( envs.Contains( 'env_novigrad_cave' ) || envs.Contains( 'cave_catacombs' ) ) { return true; } return false; } private saved var selectedPotionSlotUpper, selectedPotionSlotLower : EEquipmentSlots; private var potionDoubleTapTimerRunning, potionDoubleTapSlotIsUpper : bool; default selectedPotionSlotUpper = EES_Potion1; default selectedPotionSlotLower = EES_Potion2; default potionDoubleTapTimerRunning = false; public final function SetPotionDoubleTapRunning(b : bool, optional isUpperSlot : bool) { if(b) { AddTimer('PotionDoubleTap', 0.3); } else { RemoveTimer('PotionDoubleTap'); } potionDoubleTapTimerRunning = b; potionDoubleTapSlotIsUpper = isUpperSlot; } public final function IsPotionDoubleTapRunning() : bool { return potionDoubleTapTimerRunning; } timer function PotionDoubleTap(dt : float, id : int) { potionDoubleTapTimerRunning = false; OnPotionDrinkInput(potionDoubleTapSlotIsUpper); } public final function OnPotionDrinkInput(fromUpperSlot : bool) { var slot : EEquipmentSlots; if(fromUpperSlot) slot = GetSelectedPotionSlotUpper(); else slot = GetSelectedPotionSlotLower(); DrinkPotionFromSlot(slot); } public final function OnPotionDrinkKeyboardsInput(slot : EEquipmentSlots) { DrinkPotionFromSlot(slot); } private function DrinkPotionFromSlot(slot : EEquipmentSlots):void { var item : SItemUniqueId; var hud : CR4ScriptedHud; var module : CR4HudModuleItemInfo; GetItemEquippedOnSlot(slot, item); if(inv.ItemHasTag(item, 'Edibles')) { ConsumeItem( item ); } else { if (ToxicityLowEnoughToDrinkPotion(slot)) { DrinkPreparedPotion(slot); } else { SendToxicityTooHighMessage(); } } hud = (CR4ScriptedHud)theGame.GetHud(); if ( hud ) { module = (CR4HudModuleItemInfo)hud.GetHudModule("ItemInfoModule"); if( module ) { module.ForceShowElement(); } } } private function SendToxicityTooHighMessage() { var messageText : string; var language : string; var audioLanguage : string; if (GetHudMessagesSize() < 2) { messageText = GetLocStringByKeyExt("menu_cannot_perform_action_now") + " " + GetLocStringByKeyExt("panel_common_statistics_tooltip_current_toxicity"); theGame.GetGameLanguageName(audioLanguage,language); if (language == "AR") { messageText += (int)(abilityManager.GetStat(BCS_Toxicity, false)) + " / " + (int)(abilityManager.GetStatMax(BCS_Toxicity)) + " :"; } else { messageText += ": " + (int)(abilityManager.GetStat(BCS_Toxicity, false)) + " / " + (int)(abilityManager.GetStatMax(BCS_Toxicity)); } DisplayHudMessage(messageText); } theSound.SoundEvent("gui_global_denied"); } public final function GetSelectedPotionSlotUpper() : EEquipmentSlots { return selectedPotionSlotUpper; } public final function GetSelectedPotionSlotLower() : EEquipmentSlots { return selectedPotionSlotLower; } public final function FlipSelectedPotion(isUpperSlot : bool) : bool { if(isUpperSlot) { if(selectedPotionSlotUpper == EES_Potion1 && IsAnyItemEquippedOnSlot(EES_Potion3)) { selectedPotionSlotUpper = EES_Potion3; return true; } else if(selectedPotionSlotUpper == EES_Potion3 && IsAnyItemEquippedOnSlot(EES_Potion1)) { selectedPotionSlotUpper = EES_Potion1; return true; } } else { if(selectedPotionSlotLower == EES_Potion2 && IsAnyItemEquippedOnSlot(EES_Potion4)) { selectedPotionSlotLower = EES_Potion4; return true; } else if(selectedPotionSlotLower == EES_Potion4 && IsAnyItemEquippedOnSlot(EES_Potion2)) { selectedPotionSlotLower = EES_Potion2; return true; } } return false; } public final function AddBombThrowDelay( bombId : SItemUniqueId ) { var slot : EEquipmentSlots; slot = GetItemSlot( bombId ); if( slot == EES_Unused ) { return; } if( slot == EES_Petard1 || slot == EES_Quickslot1 ) { remainingBombThrowDelaySlot1 = theGame.params.BOMB_THROW_DELAY; AddTimer( 'BombDelay', 0.0f, true ); } else if( slot == EES_Petard2 || slot == EES_Quickslot2 ) { remainingBombThrowDelaySlot2 = theGame.params.BOMB_THROW_DELAY; AddTimer( 'BombDelay', 0.0f, true ); } else { return; } } public final function GetBombDelay( slot : EEquipmentSlots ) : float { if( slot == EES_Petard1 || slot == EES_Quickslot1 ) { return remainingBombThrowDelaySlot1; } else if( slot == EES_Petard2 || slot == EES_Quickslot2 ) { return remainingBombThrowDelaySlot2; } return 0; } timer function BombDelay( dt : float, id : int ) { remainingBombThrowDelaySlot1 = MaxF( 0.f , remainingBombThrowDelaySlot1 - dt ); remainingBombThrowDelaySlot2 = MaxF( 0.f , remainingBombThrowDelaySlot2 - dt ); if( remainingBombThrowDelaySlot1 <= 0.0f && remainingBombThrowDelaySlot2 <= 0.0f ) { RemoveTimer('BombDelay'); } } public function ResetCharacterDev() { UnequipItemFromSlot(EES_SkillMutagen1); UnequipItemFromSlot(EES_SkillMutagen2); UnequipItemFromSlot(EES_SkillMutagen3); UnequipItemFromSlot(EES_SkillMutagen4); levelManager.ResetCharacterDev(); ((W3PlayerAbilityManager)abilityManager).ResetCharacterDev(); } public final function ResetMutationsDev() { levelManager.ResetMutationsDev(); ((W3PlayerAbilityManager)abilityManager).ResetMutationsDev(); } public final function GetHeldSword() : SItemUniqueId { var i : int; var weapons : array< SItemUniqueId >; weapons = inv.GetHeldWeapons(); for( i=0; i { if( inv.IsItemSilverSwordUsableByPlayer( weapons[i] ) || inv.IsItemSteelSwordUsableByPlayer( weapons[i] ) ) { return weapons[i]; } } return GetInvalidUniqueId(); } public function ConsumeItem( itemId : SItemUniqueId ) : bool { var itemName : name; var removedItem, willRemoveItem : bool; var edibles : array; var toSlot : EEquipmentSlots; var i : int; var equippedNewEdible : bool; itemName = inv.GetItemName( itemId ); if (itemName == 'q111_imlerith_acorn' ) { AddPoints(ESkillPoint, 2, true); removedItem = inv.RemoveItem( itemId, 1 ); theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt("panel_character_popup_title_buy_skill") + " " + GetLocStringByKeyExt("panel_character_availablepoints") + " +2"); theSound.SoundEvent("gui_character_buy_skill"); } else if ( itemName == 'Clearing Potion' ) { ResetCharacterDev(); removedItem = inv.RemoveItem( itemId, 1 ); theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt("panel_character_popup_character_cleared") ); theSound.SoundEvent("gui_character_synergy_effect"); } else if ( itemName == 'Restoring Potion' ) { ResetMutationsDev(); removedItem = inv.RemoveItem( itemId, 1 ); theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt("panel_character_popup_character_cleared") ); theSound.SoundEvent("gui_character_synergy_effect"); } else if(itemName == 'Wolf Hour') { removedItem = inv.RemoveItem( itemId, 1 ); theSound.SoundEvent("gui_character_synergy_effect"); AddEffectDefault(EET_WolfHour, thePlayer, 'wolf hour'); } else if ( itemName == 'q704_ft_golden_egg' ) { AddPoints(ESkillPoint, 1, true); removedItem = inv.RemoveItem( itemId, 1 ); theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt("panel_character_popup_title_buy_skill") + " " + GetLocStringByKeyExt("panel_character_availablepoints") + " +1"); theSound.SoundEvent("gui_character_buy_skill"); } else if ( itemName == 'mq7023_cake' ) { this.AddAbility('mq7023_cake_vitality_bonus'); removedItem = inv.RemoveItem( itemId, 1 ); theSound.SoundEvent("gui_character_synergy_effect"); } else { willRemoveItem = inv.GetItemQuantity(itemId) == 1 && !inv.ItemHasTag(itemId, 'InfiniteUse'); if(willRemoveItem) toSlot = GetItemSlot(itemId); removedItem = super.ConsumeItem(itemId); if(willRemoveItem && removedItem) { edibles = inv.GetItemsByTag('Edibles'); equippedNewEdible = false; for(i=0; i { if(!IsItemEquipped(edibles[i]) && !inv.ItemHasTag(edibles[i], 'Alcohol') && inv.GetItemName(edibles[i]) != 'Clearing Potion' && inv.GetItemName(edibles[i]) != 'Wolf Hour') { EquipItemInGivenSlot(edibles[i], toSlot, true, false); equippedNewEdible = true; break; } } if(!equippedNewEdible) { for(i=0; i { if(!IsItemEquipped(edibles[i]) && inv.GetItemName(edibles[i]) != 'Clearing Potion' && inv.GetItemName(edibles[i]) != 'Wolf Hour') { EquipItemInGivenSlot(edibles[i], toSlot, true, false); break; } } } } } return removedItem; } public final function GetAlcoholForAlchemicalItemsRefill() : SItemUniqueId { var alcos : array; var id : SItemUniqueId; var i, price, minPrice : int; alcos = inv.GetItemsByTag(theGame.params.TAG_ALCHEMY_REFILL_ALCO); if(alcos.Size() > 0) { if(inv.ItemHasTag(alcos[0], theGame.params.TAG_INFINITE_USE)) return alcos[0]; minPrice = inv.GetItemPrice(alcos[0]); price = minPrice; id = alcos[0]; for(i=1; i { if(inv.ItemHasTag(alcos[i], theGame.params.TAG_INFINITE_USE)) return alcos[i]; price = inv.GetItemPrice(alcos[i]); if(price < minPrice) { minPrice = price; id = alcos[i]; } } return id; } return GetInvalidUniqueId(); } public final function ClearPreviouslyUsedBolt() { previouslyUsedBolt = GetInvalidUniqueId(); } public function GetCurrentInfiniteBoltName( optional forceBodkin : bool, optional forceHarpoon : bool ) : name { if(!forceBodkin && (forceHarpoon || GetCurrentStateName() == 'Swimming' || IsSwimming() || IsDiving()) ) { return 'Harpoon Bolt'; } return 'Bodkin Bolt'; } public final function AddAndEquipInfiniteBolt(optional forceBodkin : bool, optional forceHarpoon : bool) { var bolt, bodkins, harpoons : array; var boltItemName : name; var i : int; bodkins = inv.GetItemsByName('Bodkin Bolt'); harpoons = inv.GetItemsByName('Harpoon Bolt'); for(i=bodkins.Size()-1; i>=0; i-=1) inv.RemoveItem(bodkins[i], inv.GetItemQuantity(bodkins[i]) ); for(i=harpoons.Size()-1; i>=0; i-=1) inv.RemoveItem(harpoons[i], inv.GetItemQuantity(harpoons[i]) ); boltItemName = GetCurrentInfiniteBoltName( forceBodkin, forceHarpoon ); if(boltItemName == 'Bodkin Bolt' && inv.IsIdValid(previouslyUsedBolt)) { bolt.PushBack(previouslyUsedBolt); } else { bolt = inv.AddAnItem(boltItemName, 1, true, true); if(boltItemName == 'Harpoon Bolt') { GetItemEquippedOnSlot(EES_Bolt, previouslyUsedBolt); } } EquipItem(bolt[0], EES_Bolt); } event OnItemGiven(data : SItemChangedData) { var m_guiManager : CR4GuiManager; super.OnItemGiven(data); if(!inv) inv = GetInventory(); if(inv.IsItemEncumbranceItem(data.ids[0])) UpdateEncumbrance(); m_guiManager = theGame.GetGuiManager(); if(m_guiManager) m_guiManager.RegisterNewItem(data.ids[0]); } public final function CheckForFullyArmedAchievement() { if( HasAllItemsFromSet(theGame.params.ITEM_SET_TAG_BEAR) || HasAllItemsFromSet(theGame.params.ITEM_SET_TAG_GRYPHON) || HasAllItemsFromSet(theGame.params.ITEM_SET_TAG_LYNX) || HasAllItemsFromSet(theGame.params.ITEM_SET_TAG_WOLF) || HasAllItemsFromSet(theGame.params.ITEM_SET_TAG_VIPER) ) { theGame.GetGamerProfile().AddAchievement(EA_FullyArmed); } } public final function HasAllItemsFromSet(setItemTag : name) : bool { var item : SItemUniqueId; if(!GetItemEquippedOnSlot(EES_SteelSword, item) || !inv.ItemHasTag(item, setItemTag)) return false; if(!GetItemEquippedOnSlot(EES_SilverSword, item) || !inv.ItemHasTag(item, setItemTag)) return false; if(!GetItemEquippedOnSlot(EES_Boots, item) || !inv.ItemHasTag(item, setItemTag)) return false; if(!GetItemEquippedOnSlot(EES_Pants, item) || !inv.ItemHasTag(item, setItemTag)) return false; if(!GetItemEquippedOnSlot(EES_Gloves, item) || !inv.ItemHasTag(item, setItemTag)) return false; if(!GetItemEquippedOnSlot(EES_Armor, item) || !inv.ItemHasTag(item, setItemTag)) return false; if(setItemTag == theGame.params.ITEM_SET_TAG_BEAR || setItemTag == theGame.params.ITEM_SET_TAG_LYNX) { if(!GetItemEquippedOnSlot(EES_RangedWeapon, item) || !inv.ItemHasTag(item, setItemTag)) return false; } return true; } public function GetTotalArmor() : SAbilityAttributeValue { var armor : SAbilityAttributeValue; var armorItem : SItemUniqueId; armor = super.GetTotalArmor(); if(GetItemEquippedOnSlot(EES_Armor, armorItem)) { armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); armor += inv.GetItemArmorTotal(armorItem); } if(GetItemEquippedOnSlot(EES_Pants, armorItem)) { armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); armor += inv.GetItemArmorTotal(armorItem); } if(GetItemEquippedOnSlot(EES_Boots, armorItem)) { armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); armor += inv.GetItemArmorTotal(armorItem); } if(GetItemEquippedOnSlot(EES_Gloves, armorItem)) { armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); armor += inv.GetItemArmorTotal(armorItem); } return armor; } public function ReduceArmorDurability() : EEquipmentSlots { var r, sum : int; var slot : EEquipmentSlots; var id : SItemUniqueId; var prevDurMult, currDurMult, ratio : float; sum = theGame.params.DURABILITY_ARMOR_CHEST_WEIGHT; sum += theGame.params.DURABILITY_ARMOR_PANTS_WEIGHT; sum += theGame.params.DURABILITY_ARMOR_GLOVES_WEIGHT; sum += theGame.params.DURABILITY_ARMOR_BOOTS_WEIGHT; sum += theGame.params.DURABILITY_ARMOR_MISS_WEIGHT; r = RandRange(sum); if(r < theGame.params.DURABILITY_ARMOR_CHEST_WEIGHT) slot = EES_Armor; else if (r < theGame.params.DURABILITY_ARMOR_CHEST_WEIGHT + theGame.params.DURABILITY_ARMOR_PANTS_WEIGHT) slot = EES_Pants; else if (r < theGame.params.DURABILITY_ARMOR_CHEST_WEIGHT + theGame.params.DURABILITY_ARMOR_PANTS_WEIGHT + theGame.params.DURABILITY_ARMOR_GLOVES_WEIGHT) slot = EES_Gloves; else if (r < theGame.params.DURABILITY_ARMOR_CHEST_WEIGHT + theGame.params.DURABILITY_ARMOR_PANTS_WEIGHT + theGame.params.DURABILITY_ARMOR_GLOVES_WEIGHT + theGame.params.DURABILITY_ARMOR_BOOTS_WEIGHT) slot = EES_Boots; else return EES_InvalidSlot; GetItemEquippedOnSlot(slot, id); ratio = inv.GetItemDurabilityRatio(id); if(inv.ReduceItemDurability(id)) { prevDurMult = theGame.params.GetDurabilityMultiplier(ratio, false); ratio = inv.GetItemDurabilityRatio(id); currDurMult = theGame.params.GetDurabilityMultiplier(ratio, false); if(currDurMult != prevDurMult) { } return slot; } return EES_InvalidSlot; } public function DismantleItem(dismantledItem : SItemUniqueId, toolItem : SItemUniqueId) : bool { var parts : array; var i : int; if(!inv.IsItemDismantleKit(toolItem)) return false; parts = inv.GetItemRecyclingParts(dismantledItem); if(parts.Size() <= 0) return false; for(i=0; i inv.AddAnItem(parts[i].itemName, parts[i].quantity, true, false); inv.RemoveItem(toolItem); inv.RemoveItem(dismantledItem); return true; } public function GetItemEquippedOnSlot(slot : EEquipmentSlots, out item : SItemUniqueId) : bool { if(slot == EES_InvalidSlot || slot < 0 || slot > EnumGetMax('EEquipmentSlots')) return false; item = itemSlots[slot]; return inv.IsIdValid(item); } public function GetItemSlotByItemName(itemName : name) : EEquipmentSlots { var ids : array; var i : int; var slot : EEquipmentSlots; ids = inv.GetItemsByName(itemName); for(i=0; i { slot = GetItemSlot(ids[i]); if(slot != EES_InvalidSlot) return slot; } return EES_InvalidSlot; } public function GetItemSlot(item : SItemUniqueId) : EEquipmentSlots { var i : int; if(!inv.IsIdValid(item)) return EES_InvalidSlot; for(i=0; i if(itemSlots[i] == item) return i; return EES_InvalidSlot; } public function GetEquippedItems() : array { return itemSlots; } public function IsItemEquipped(item : SItemUniqueId) : bool { if(!inv.IsIdValid(item)) return false; return itemSlots.Contains(item); } public function IsItemHeld(item : SItemUniqueId) : bool { if(!inv.IsIdValid(item)) return false; return inv.IsItemHeld(item); } public function IsAnyItemEquippedOnSlot(slot : EEquipmentSlots) : bool { if(slot == EES_InvalidSlot || slot < 0 || slot > EnumGetMax('EEquipmentSlots')) return false; return inv.IsIdValid(itemSlots[slot]); } public function GetFreeQuickslot() : EEquipmentSlots { if(!inv.IsIdValid(itemSlots[EES_Quickslot1])) return EES_Quickslot1; if(!inv.IsIdValid(itemSlots[EES_Quickslot2])) return EES_Quickslot2; return EES_InvalidSlot; } event OnEquipItemRequested(item : SItemUniqueId, ignoreMount : bool) { var slot : EEquipmentSlots; if(inv.IsIdValid(item)) { slot = inv.GetSlotForItemId(item); if (slot != EES_InvalidSlot) { EquipItemInGivenSlot(item, slot, ignoreMount); } } } event OnUnequipItemRequested(item : SItemUniqueId) { UnequipItem(item); } public function EquipItem(item : SItemUniqueId, optional slot : EEquipmentSlots, optional toHand : bool) : bool { if(!inv.IsIdValid(item)) return false; if(slot == EES_InvalidSlot) { slot = inv.GetSlotForItemId(item); if(slot == EES_InvalidSlot) return false; } ForceSoundAppearanceUpdate(); return EquipItemInGivenSlot(item, slot, false, toHand); } protected function ShouldMount(slot : EEquipmentSlots, item : SItemUniqueId, category : name):bool { return !IsSlotPotionMutagen(slot) && category != 'usable' && category != 'potion' && category != 'petard' && !inv.ItemHasTag(item, 'PlayerUnwearable'); } protected function ShouldMountItemWithName( itemName: name ): bool { var slot : EEquipmentSlots; var items : array; var category : name; var i : int; items = inv.GetItemsByName( itemName ); category = inv.GetItemCategory( items[0] ); slot = GetItemSlot( items[0] ); return ShouldMount( slot, items[0], category ); } public function GetMountableItems( out items : array< SItemUniqueId > ) { var i : int; var mountable : bool; var mountableItems : array< SItemUniqueId >; var slot : EEquipmentSlots; var category : name; var item: SItemUniqueId; for ( i = 0; i < items.Size(); i += 1 ) { item = items[i]; category = inv.GetItemCategory( item ); slot = GetItemSlot( item ); mountable = ShouldMount( slot, item, category ); if ( mountable ) { mountableItems.PushBack( items[ i ] ); } } items = mountableItems; } public final function AddAndEquipItem( item : name ) : bool { var ids : array< SItemUniqueId >; ids = inv.AddAnItem( item ); if( inv.IsIdValid( ids[ 0 ] ) ) { return EquipItem( ids[ 0 ] ); } return false; } public final function AddQuestMarkedSelectedQuickslotItem( sel : SSelectedQuickslotItem ) { questMarkedSelectedQuickslotItems.PushBack( sel ); } public final function GetQuestMarkedSelectedQuickslotItem( sourceName : name ) : SItemUniqueId { var i : int; for( i=0; i { if( questMarkedSelectedQuickslotItems[i].sourceName == sourceName ) { return questMarkedSelectedQuickslotItems[i].itemID; } } return GetInvalidUniqueId(); } public final function SwapEquippedItems(slot1 : EEquipmentSlots, slot2 : EEquipmentSlots) { var temp : SItemUniqueId; var pam : W3PlayerAbilityManager; temp = itemSlots[slot1]; itemSlots[slot1] = itemSlots[slot2]; itemSlots[slot2] = temp; if(IsSlotSkillMutagen(slot1)) { pam = (W3PlayerAbilityManager)abilityManager; if(pam) pam.OnSwappedMutagensPost(itemSlots[slot1], itemSlots[slot2]); } } public final function GetSlotForEquippedItem( itemID : SItemUniqueId ) : EEquipmentSlots { var i : int; for( i=0; i { if( itemSlots[i] == itemID ) { return i; } } return EES_InvalidSlot; } public function EquipItemInGivenSlot(item : SItemUniqueId, slot : EEquipmentSlots, ignoreMounting : bool, optional toHand : bool) : bool { var i, groupID : int; var fistsID : array; var pam : W3PlayerAbilityManager; var isSkillMutagen : bool; var armorEntity : CItemEntity; var armorMeshComponent : CComponent; var armorSoundIdentification : name; var category : name; var prevSkillColor : ESkillColor; var containedAbilities : array; var dm : CDefinitionsManagerAccessor; var armorType : EArmorType; var otherMask, previousItemInSlot : SItemUniqueId; var tutStatePot : W3TutorialManagerUIHandlerStatePotions; var tutStateFood : W3TutorialManagerUIHandlerStateFood; var tutStateSecondPotionEquip : W3TutorialManagerUIHandlerStateSecondPotionEquip; var boltItem : SItemUniqueId; var aerondight : W3Effect_Aerondight; if(!inv.IsIdValid(item)) { LogAssert(false, "W3PlayerWitcher.EquipItemInGivenSlot: invalid item"); return false; } if(slot == EES_InvalidSlot || slot == EES_HorseBlinders || slot == EES_HorseSaddle || slot == EES_HorseBag || slot == EES_HorseTrophy) { LogAssert(false, "W3PlayerWitcher.EquipItem: Cannot equip item <<" + inv.GetItemName(item) + ">> - provided slot <<" + slot + ">> is invalid"); return false; } if(itemSlots[slot] == item) { return true; } if(!HasRequiredLevelToEquipItem(item)) { return false; } if(inv.ItemHasTag(item, 'PhantomWeapon') && !GetPhantomWeaponMgr()) { InitPhantomWeaponMgr(); } if( slot == EES_SilverSword && inv.ItemHasTag( item, 'Aerondight' ) ) { AddEffectDefault( EET_Aerondight, this, "Aerondight" ); aerondight = (W3Effect_Aerondight)GetBuff( EET_Aerondight ); aerondight.Pause( 'ManageAerondightBuff' ); } previousItemInSlot = itemSlots[slot]; if( IsItemEquipped(item)) { SwapEquippedItems(slot, GetItemSlot(item)); return true; } isSkillMutagen = IsSlotSkillMutagen(slot); if(isSkillMutagen) { pam = (W3PlayerAbilityManager)abilityManager; if(!pam.IsSkillMutagenSlotUnlocked(slot)) { return false; } } if(inv.IsIdValid(previousItemInSlot)) { if(!UnequipItemFromSlot(slot, true)) { LogAssert(false, "W3PlayerWitcher.EquipItem: Cannot equip item <<" + inv.GetItemName(item) + ">> !!"); return false; } } if(inv.IsItemMask(item)) { if(slot == EES_Quickslot1) GetItemEquippedOnSlot(EES_Quickslot2, otherMask); else GetItemEquippedOnSlot(EES_Quickslot1, otherMask); if(inv.IsItemMask(otherMask)) UnequipItem(otherMask); } if(isSkillMutagen) { groupID = pam.GetSkillGroupIdOfMutagenSlot(slot); prevSkillColor = pam.GetSkillGroupColor(groupID); } itemSlots[slot] = item; category = inv.GetItemCategory( item ); if( !ignoreMounting && ShouldMount(slot, item, category) ) { inv.MountItem( item, toHand, IsSlotSkillMutagen( slot ) ); } theTelemetry.LogWithLabelAndValue( TE_INV_ITEM_EQUIPPED, inv.GetItemName(item), slot ); if(slot == EES_RangedWeapon) { rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe(item) ); if(!rangedWeapon) AddTimer('DelayedOnItemMount', 0.1, true); if ( IsSwimming() || IsDiving() ) { GetItemEquippedOnSlot(EES_Bolt, boltItem); if(inv.IsIdValid(boltItem)) { if ( !inv.ItemHasTag(boltItem, 'UnderwaterAmmo' )) { AddAndEquipInfiniteBolt(false, true); } } else if(!IsAnyItemEquippedOnSlot(EES_Bolt)) { AddAndEquipInfiniteBolt(false, true); } } else if(!IsAnyItemEquippedOnSlot(EES_Bolt)) AddAndEquipInfiniteBolt(); } else if(slot == EES_Bolt) { if(rangedWeapon) { if ( !IsSwimming() || !IsDiving() ) { rangedWeapon.OnReplaceAmmo(); rangedWeapon.OnWeaponReload(); } else { DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_now" )); } } } else if(isSkillMutagen) { pam.OnSkillMutagenEquipped(item, slot, prevSkillColor); LogSkillColors("Mutagen <<" + inv.GetItemName(item) + ">> equipped to slot <<" + slot + ">>"); LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>"); LogSkillColors(""); } else if(slot == EES_Gloves && HasWeaponDrawn(false)) { PlayRuneword4FX(PW_Steel); PlayRuneword4FX(PW_Silver); } else if( ( slot == EES_Petard1 || slot == EES_Petard2 ) && inv.IsItemBomb( GetSelectedItemId() ) ) { SelectQuickslotItem( slot ); } if(inv.ItemHasAbility(item, 'MA_HtH')) { inv.GetItemContainedAbilities(item, containedAbilities); fistsID = inv.GetItemsByName('fists'); dm = theGame.GetDefinitionsManager(); for(i=0; i { if(dm.AbilityHasTag(containedAbilities[i], 'MA_HtH')) { inv.AddItemCraftedAbility(fistsID[0], containedAbilities[i], true); } } } if(inv.IsItemAnyArmor(item)) { armorType = inv.GetArmorType(item); pam = (W3PlayerAbilityManager)abilityManager; if(armorType == EAT_Light) { if(CanUseSkill(S_Perk_05)) pam.SetPerkArmorBonus(S_Perk_05); } else if(armorType == EAT_Medium) { if(CanUseSkill(S_Perk_06)) pam.SetPerkArmorBonus(S_Perk_06); } else if(armorType == EAT_Heavy) { if(CanUseSkill(S_Perk_07)) pam.SetPerkArmorBonus(S_Perk_07); } } UpdateItemSetBonuses( item, true ); theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnItemEquipped ); if(ShouldProcessTutorial('TutorialPotionCanEquip3')) { if(IsSlotPotionSlot(slot)) { tutStatePot = (W3TutorialManagerUIHandlerStatePotions)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutStatePot) { tutStatePot.OnPotionEquipped(inv.GetItemName(item)); } tutStateSecondPotionEquip = (W3TutorialManagerUIHandlerStateSecondPotionEquip)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutStateSecondPotionEquip) { tutStateSecondPotionEquip.OnPotionEquipped(inv.GetItemName(item)); } } } if(ShouldProcessTutorial('TutorialFoodSelectTab')) { if( IsSlotPotionSlot(slot) && inv.IsItemFood(item)) { tutStateFood = (W3TutorialManagerUIHandlerStateFood)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutStateFood) { tutStateFood.OnFoodEquipped(); } } } if(inv.IsItemSetItem(item)) { CheckForFullyArmedAchievement(); } return true; } private function CheckHairItem() { var ids : array; var i : int; var itemName : name; var hairApplied : bool; ids = inv.GetItemsByCategory('hair'); for(i=0; i { itemName = inv.GetItemName( ids[i] ); if( itemName != 'Preview Hair' ) { if( hairApplied == false ) { inv.MountItem( ids[i], false ); hairApplied = true; } else { inv.RemoveItem( ids[i], 1 ); } } } if( hairApplied == false ) { ids = inv.AddAnItem('Half With Tail Hairstyle', 1, true, false); inv.MountItem( ids[0], false ); } } timer function DelayedOnItemMount( dt : float, id : int ) { var crossbowID : SItemUniqueId; var invent : CInventoryComponent; invent = GetInventory(); if(!invent) return; GetItemEquippedOnSlot(EES_RangedWeapon, crossbowID); if(invent.IsIdValid(crossbowID)) { rangedWeapon = ( Crossbow )(invent.GetItemEntityUnsafe(crossbowID) ); if(rangedWeapon) { RemoveTimer('DelayedOnItemMount'); } } else { RemoveTimer('DelayedOnItemMount'); } } public function GetHeldItems() : array { var items : array; var item : SItemUniqueId; if( inv.GetItemEquippedOnSlot(EES_SilverSword, item) && inv.IsItemHeld(item)) items.PushBack(item); if( inv.GetItemEquippedOnSlot(EES_SteelSword, item) && inv.IsItemHeld(item)) items.PushBack(item); if( inv.GetItemEquippedOnSlot(EES_RangedWeapon, item) && inv.IsItemHeld(item)) items.PushBack(item); if( inv.GetItemEquippedOnSlot(EES_Quickslot1, item) && inv.IsItemHeld(item)) items.PushBack(item); if( inv.GetItemEquippedOnSlot(EES_Quickslot2, item) && inv.IsItemHeld(item)) items.PushBack(item); if( inv.GetItemEquippedOnSlot(EES_Petard1, item) && inv.IsItemHeld(item)) items.PushBack(item); if( inv.GetItemEquippedOnSlot(EES_Petard2, item) && inv.IsItemHeld(item)) items.PushBack(item); return items; } public function UnequipItemFromSlot(slot : EEquipmentSlots, optional reequipped : bool) : bool { var item, bolts, id : SItemUniqueId; var items : array; var retBool : bool; var fistsID, bolt : array; var i, groupID : int; var pam : W3PlayerAbilityManager; var prevSkillColor : ESkillColor; var containedAbilities : array; var dm : CDefinitionsManagerAccessor; var armorType : EArmorType; var isSwimming : bool; var hud : CR4ScriptedHud; var damagedItemModule : CR4HudModuleDamagedItems; if(slot == EES_InvalidSlot || slot < 0 || slot > EnumGetMax('EEquipmentSlots') || !inv.IsIdValid(itemSlots[slot])) return false; if(IsSlotSkillMutagen(slot)) { pam = (W3PlayerAbilityManager)abilityManager; groupID = pam.GetSkillGroupIdOfMutagenSlot(slot); prevSkillColor = pam.GetSkillGroupColor(groupID); } if(slot == EES_SilverSword || slot == EES_SteelSword) { PauseOilBuffs( slot == EES_SteelSword ); } item = itemSlots[slot]; itemSlots[slot] = GetInvalidUniqueId(); if(inv.ItemHasTag( item, 'PhantomWeapon' ) && GetPhantomWeaponMgr()) { DestroyPhantomWeaponMgr(); } if( slot == EES_SilverSword && inv.ItemHasTag( item, 'Aerondight' ) ) { RemoveBuff( EET_Aerondight ); } if(slot == EES_RangedWeapon) { this.OnRangedForceHolster( true, true ); rangedWeapon.ClearDeployedEntity(true); rangedWeapon = NULL; if(GetItemEquippedOnSlot(EES_Bolt, bolts)) { if(inv.ItemHasTag(bolts, theGame.params.TAG_INFINITE_AMMO)) { inv.RemoveItem(bolts, inv.GetItemQuantity(bolts) ); } } } else if(IsSlotSkillMutagen(slot)) { pam.OnSkillMutagenUnequipped(item, slot, prevSkillColor); LogSkillColors("Mutagen <<" + inv.GetItemName(item) + ">> unequipped from slot <<" + slot + ">>"); LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>"); LogSkillColors(""); } if(currentlyEquipedItem == item) { currentlyEquipedItem = GetInvalidUniqueId(); RaiseEvent('ForcedUsableItemUnequip'); } if(currentlyEquipedItemL == item) { if ( currentlyUsedItemL ) { currentlyUsedItemL.OnHidden( this ); } HideUsableItem ( true ); } if( !IsSlotPotionMutagen(slot) ) { GetInventory().UnmountItem(item, true); } retBool = true; if(IsAnyItemEquippedOnSlot(EES_RangedWeapon) && slot == EES_Bolt) { if(inv.ItemHasTag(item, theGame.params.TAG_INFINITE_AMMO)) { inv.RemoveItem(item, inv.GetItemQuantityByName( inv.GetItemName(item) ) ); } else if (!reequipped) { AddAndEquipInfiniteBolt(); } } if(slot == EES_SilverSword || slot == EES_SteelSword) { OnEquipMeleeWeapon(PW_None, true); } if( GetSelectedItemId() == item ) { ClearSelectedItemId(); } if(inv.IsItemBody(item)) { retBool = true; } if(retBool && !reequipped) { theTelemetry.LogWithLabelAndValue( TE_INV_ITEM_UNEQUIPPED, inv.GetItemName(item), slot ); if(slot == EES_SteelSword && !IsAnyItemEquippedOnSlot(EES_SilverSword)) { RemoveBuff(EET_EnhancedWeapon); } else if(slot == EES_SilverSword && !IsAnyItemEquippedOnSlot(EES_SteelSword)) { RemoveBuff(EET_EnhancedWeapon); } else if(inv.IsItemAnyArmor(item)) { if( !IsAnyItemEquippedOnSlot(EES_Armor) && !IsAnyItemEquippedOnSlot(EES_Gloves) && !IsAnyItemEquippedOnSlot(EES_Boots) && !IsAnyItemEquippedOnSlot(EES_Pants)) RemoveBuff(EET_EnhancedArmor); } } if(inv.ItemHasAbility(item, 'MA_HtH')) { inv.GetItemContainedAbilities(item, containedAbilities); fistsID = inv.GetItemsByName('fists'); dm = theGame.GetDefinitionsManager(); for(i=0; i { if(dm.AbilityHasTag(containedAbilities[i], 'MA_HtH')) { inv.RemoveItemCraftedAbility(fistsID[0], containedAbilities[i]); } } } if(inv.IsItemAnyArmor(item)) { armorType = inv.GetArmorType(item); pam = (W3PlayerAbilityManager)abilityManager; if(CanUseSkill(S_Perk_05) && (armorType == EAT_Light || GetCharacterStats().HasAbility('Glyphword 2 _Stats', true) || inv.ItemHasAbility(item, 'Glyphword 2 _Stats'))) { pam.SetPerkArmorBonus(S_Perk_05); } if(CanUseSkill(S_Perk_06) && (armorType == EAT_Medium || GetCharacterStats().HasAbility('Glyphword 3 _Stats', true) || inv.ItemHasAbility(item, 'Glyphword 3 _Stats')) ) { pam.SetPerkArmorBonus(S_Perk_06); } if(CanUseSkill(S_Perk_07) && (armorType == EAT_Heavy || GetCharacterStats().HasAbility('Glyphword 4 _Stats', true) || inv.ItemHasAbility(item, 'Glyphword 4 _Stats')) ) { pam.SetPerkArmorBonus(S_Perk_07); } } UpdateItemSetBonuses( item, false ); if( inv.ItemHasTag( item, theGame.params.ITEM_SET_TAG_BONUS ) && !IsSetBonusActive( EISB_RedWolf_2 ) ) { SkillReduceBombAmmoBonus(); } if( slot == EES_Gloves ) { thePlayer.DestroyEffect('runeword_4'); } hud = (CR4ScriptedHud)theGame.GetHud(); if ( hud ) { damagedItemModule = hud.GetDamagedItemModule(); if ( damagedItemModule ) { damagedItemModule.OnItemUnequippedFromSlot( slot ); } } theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnItemEquipped ); return retBool; } public function UnequipItem(item : SItemUniqueId) : bool { if(!inv.IsIdValid(item)) return false; return UnequipItemFromSlot( itemSlots.FindFirst(item) ); } public function DropItem( item : SItemUniqueId, quantity : int ) : bool { if(!inv.IsIdValid(item)) return false; if(IsItemEquipped(item)) return UnequipItem(item); return true; } public function IsItemEquippedByName(itemName : name) : bool { var i : int; for(i=0; i if(inv.GetItemName(itemSlots[i]) == itemName) return true; return false; } public function IsItemEquippedByCategoryName(categoryName : name) : bool { var i : int; for(i=0; i if(inv.GetItemCategory(itemSlots[i]) == categoryName) return true; return false; } public function GetMaxRunEncumbrance(out usesHorseBonus : bool) : float { var value : float; value = CalculateAttributeValue(GetHorseManager().GetHorseAttributeValue('encumbrance', false)); usesHorseBonus = (value > 0); value += CalculateAttributeValue( GetAttributeValue('encumbrance') ); return value; } public function GetEncumbrance() : float { var i: int; var encumbrance : float; var items : array; var inve : CInventoryComponent; inve = GetInventory(); inve.GetAllItems(items); for(i=0; i { encumbrance += inve.GetItemEncumbrance( items[i] ); } return encumbrance; } public function StartInvUpdateTransaction():void { invUpdateTransaction = true; } public function FinishInvUpdateTransaction():void { invUpdateTransaction = false; UpdateEncumbrance(); } public function UpdateEncumbrance() { var temp : bool; if (invUpdateTransaction) { return; } if ( GetEncumbrance() >= (GetMaxRunEncumbrance(temp) + 1) ) { if( !HasBuff(EET_OverEncumbered) && FactsQuerySum( "DEBUG_EncumbranceBoy" ) == 0 ) { AddEffectDefault(EET_OverEncumbered, NULL, "OverEncumbered"); } } else if(HasBuff(EET_OverEncumbered)) { RemoveAllBuffsOfType(EET_OverEncumbered); } } public final function GetSkillGroupIDFromIndex(idx : int) : int { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; if(pam && pam.IsInitialized()) return pam.GetSkillGroupIDFromIndex(idx); return -1; } public final function GetSkillGroupColor(groupID : int) : ESkillColor { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; if(pam && pam.IsInitialized()) return pam.GetSkillGroupColor(groupID); return SC_None; } public final function GetSkillGroupsCount() : int { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; if(pam && pam.IsInitialized()) return pam.GetSkillGroupsCount(); return 0; } function CycleSelectSign( bIsCyclingLeft : bool ) : ESignType { var signOrder : array; var i : int; signOrder.PushBack( ST_Yrden ); signOrder.PushBack( ST_Quen ); signOrder.PushBack( ST_Igni ); signOrder.PushBack( ST_Axii ); signOrder.PushBack( ST_Aard ); for( i = 0; i < signOrder.Size(); i += 1 ) if( signOrder[i] == equippedSign ) break; if(bIsCyclingLeft) return signOrder[ (4 + i) % 5 ]; else return signOrder[ (6 + i) % 5 ]; } function ToggleNextSign() { SetEquippedSign(CycleSelectSign( false )); FactsAdd("SignToggled", 1, 1); } function TogglePreviousSign() { SetEquippedSign(CycleSelectSign( true )); FactsAdd("SignToggled", 1, 1); } function ProcessSignEvent( eventName : name ) : bool { if( currentlyCastSign != ST_None && signs[currentlyCastSign].entity) { return signs[currentlyCastSign].entity.OnProcessSignEvent( eventName ); } return false; } var findActorTargetTimeStamp : float; var pcModeChanneledSignTimeStamp : float; event OnProcessCastingOrientation( isContinueCasting : bool ) { var customOrientationTarget : EOrientationTarget; var checkHeading : float; var rotHeading : float; var playerToHeadingDist : float; var slideTargetActor : CActor; var newLockTarget : CActor; var enableNoTargetOrientation : bool; var currTime : float; enableNoTargetOrientation = true; if ( GetDisplayTarget() && this.IsDisplayTargetTargetable() ) { enableNoTargetOrientation = false; if ( theInput.GetActionValue( 'CastSignHold' ) > 0 || this.IsCurrentSignChanneled() ) { if ( IsPCModeEnabled() ) { if ( EngineTimeToFloat( theGame.GetEngineTime() ) > pcModeChanneledSignTimeStamp + 1.f ) enableNoTargetOrientation = true; } else { if ( GetCurrentlyCastSign() == ST_Igni || GetCurrentlyCastSign() == ST_Axii ) { slideTargetActor = (CActor)GetDisplayTarget(); if ( slideTargetActor && ( !slideTargetActor.GetGameplayVisibility() || !CanBeTargetedIfSwimming( slideTargetActor ) || !slideTargetActor.IsAlive() ) ) { SetSlideTarget( NULL ); if ( ProcessLockTarget() ) slideTargetActor = (CActor)slideTarget; } if ( !slideTargetActor ) { LockToTarget( false ); enableNoTargetOrientation = true; } else if ( IsThreat( slideTargetActor ) || GetCurrentlyCastSign() == ST_Axii ) LockToTarget( true ); else { LockToTarget( false ); enableNoTargetOrientation = true; } } } } if ( !enableNoTargetOrientation ) { customOrientationTarget = OT_Actor; } } if ( enableNoTargetOrientation ) { if ( GetPlayerCombatStance() == PCS_AlertNear && theInput.GetActionValue( 'CastSignHold' ) > 0 ) { if ( GetDisplayTarget() && !slideTargetActor ) { currTime = EngineTimeToFloat( theGame.GetEngineTime() ); if ( currTime > findActorTargetTimeStamp + 1.5f ) { findActorTargetTimeStamp = currTime; newLockTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 0.f, true ); if ( newLockTarget && IsThreat( newLockTarget ) && IsCombatMusicEnabled() ) { SetTarget( newLockTarget, true ); SetMoveTargetChangeAllowed( true ); SetMoveTarget( newLockTarget ); SetMoveTargetChangeAllowed( false ); SetSlideTarget( newLockTarget ); } } } else ProcessLockTarget(); } if ( wasBRAxisPushed ) customOrientationTarget = OT_CameraOffset; else { if ( !lastAxisInputIsMovement || theInput.LastUsedPCInput() ) customOrientationTarget = OT_CameraOffset; else if ( theInput.GetActionValue( 'CastSignHold' ) > 0 ) { if ( GetOrientationTarget() == OT_CameraOffset ) customOrientationTarget = OT_CameraOffset; else if ( GetPlayerCombatStance() == PCS_AlertNear || GetPlayerCombatStance() == PCS_Guarded ) customOrientationTarget = OT_CameraOffset; else customOrientationTarget = OT_Player; } else customOrientationTarget = OT_CustomHeading; } } if ( GetCurrentlyCastSign() == ST_Quen ) { if ( theInput.LastUsedPCInput() ) { customOrientationTarget = OT_Camera; } else if ( IsCurrentSignChanneled() ) { if ( bLAxisReleased ) customOrientationTarget = OT_Player; else customOrientationTarget = OT_Camera; } else customOrientationTarget = OT_Player; } if ( GetCurrentlyCastSign() == ST_Axii && IsCurrentSignChanneled() ) { if ( slideTarget && (CActor)slideTarget ) { checkHeading = VecHeading( slideTarget.GetWorldPosition() - this.GetWorldPosition() ); rotHeading = checkHeading; playerToHeadingDist = AngleDistance( GetHeading(), checkHeading ); if ( playerToHeadingDist > 45 ) SetCustomRotation( 'ChanneledSignAxii', rotHeading, 0.0, 0.5, false ); else if ( playerToHeadingDist < -45 ) SetCustomRotation( 'ChanneledSignAxii', rotHeading, 0.0, 0.5, false ); } else { checkHeading = VecHeading( theCamera.GetCameraDirection() ); rotHeading = GetHeading(); playerToHeadingDist = AngleDistance( GetHeading(), checkHeading ); if ( playerToHeadingDist > 45 ) SetCustomRotation( 'ChanneledSignAxii', rotHeading - 22.5, 0.0, 0.5, false ); else if ( playerToHeadingDist < -45 ) SetCustomRotation( 'ChanneledSignAxii', rotHeading + 22.5, 0.0, 0.5, false ); } } if ( IsActorLockedToTarget() ) customOrientationTarget = OT_Actor; AddCustomOrientationTarget( customOrientationTarget, 'Signs' ); if ( customOrientationTarget == OT_CustomHeading ) SetOrientationTargetCustomHeading( GetCombatActionHeading(), 'Signs' ); } event OnRaiseSignEvent() { var newTarget : CActor; if ( ( !IsCombatMusicEnabled() && !CanAttackWhenNotInCombat( EBAT_CastSign, false, newTarget ) ) || ( IsOnBoat() && !IsCombatMusicEnabled() ) ) { if ( CastSignFriendly() ) return true; } else { RaiseEvent('CombatActionFriendlyEnd'); SetBehaviorVariable( 'SignNum', (int)equippedSign ); SetBehaviorVariable( 'combatActionType', (int)CAT_CastSign ); if ( IsPCModeEnabled() ) pcModeChanneledSignTimeStamp = EngineTimeToFloat( theGame.GetEngineTime() ); if( RaiseForceEvent('CombatAction') ) { OnCombatActionStart(); findActorTargetTimeStamp = EngineTimeToFloat( theGame.GetEngineTime() ); theTelemetry.LogWithValueStr(TE_FIGHT_PLAYER_USE_SIGN, SignEnumToString( equippedSign )); return true; } } return false; } function CastSignFriendly() : bool { var actor : CActor; SetBehaviorVariable( 'combatActionTypeForOverlay', (int)CAT_CastSign ); if ( RaiseCombatActionFriendlyEvent() ) { return true; } return false; } function CastSign() : bool { var equippedSignStr : string; var newSignEnt : W3SignEntity; var spawnPos : Vector; var slotMatrix : Matrix; var target : CActor; if ( IsInAir() ) { return false; } AddTemporarySkills(); if(equippedSign == ST_Aard) { CalcEntitySlotMatrix('l_weapon', slotMatrix); spawnPos = MatrixGetTranslation(slotMatrix); } else { spawnPos = GetWorldPosition(); } if( equippedSign == ST_Aard || equippedSign == ST_Igni ) { target = GetTarget(); if(target) target.SignalGameplayEvent( 'DodgeSign' ); } newSignEnt = (W3SignEntity)theGame.CreateEntity( signs[equippedSign].template, spawnPos, GetWorldRotation() ); return newSignEnt.Init( signOwner, signs[equippedSign].entity ); } private function HAX_SignToThrowItemRestore() { var action : SInputAction; action.value = theInput.GetActionValue('ThrowItemHold'); action.lastFrameValue = 0; if(IsPressed(action) && CanSetupCombatAction_Throw()) { if(inv.IsItemBomb(selectedItemId)) { BombThrowStart(); } else { UsableItemStart(); } SetThrowHold( true ); } } event OnCFMCameraZoomFail(){} public final function GetDrunkMutagens( optional sourceName : string ) : array { return effectManager.GetDrunkMutagens( sourceName ); } public final function GetPotionBuffs() : array { return effectManager.GetPotionBuffs(); } public final function RecalcPotionsDurations() { var i : int; var buffs : array; buffs = GetPotionBuffs(); for(i=0; i { buffs[i].RecalcPotionDuration(); } } public function StartFrenzy() { var ratio, duration : float; var skillLevel : int; isInFrenzy = true; skillLevel = GetSkillLevel(S_Alchemy_s16); ratio = 0.48f - skillLevel * CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s16, 'slowdown_ratio', false, true)); duration = skillLevel * CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s16, 'slowdown_duration', false, true)); theGame.SetTimeScale(ratio, theGame.GetTimescaleSource(ETS_SkillFrenzy), theGame.GetTimescalePriority(ETS_SkillFrenzy) ); AddTimer('SkillFrenzyFinish', duration * ratio, , , , true); } timer function SkillFrenzyFinish(dt : float, optional id : int) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_SkillFrenzy) ); isInFrenzy = false; } public function GetToxicityDamageThreshold() : float { var ret : float; ret = theGame.params.TOXICITY_DAMAGE_THRESHOLD; if(CanUseSkill(S_Alchemy_s01)) ret += CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s01, 'threshold', false, true)) * GetSkillLevel(S_Alchemy_s01); return ret; } public final function AddToxicityOffset( val : float) { ((W3PlayerAbilityManager)abilityManager).AddToxicityOffset(val); } public final function SetToxicityOffset( val : float) { ((W3PlayerAbilityManager)abilityManager).SetToxicityOffset(val); } public final function RemoveToxicityOffset( val : float) { ((W3PlayerAbilityManager)abilityManager).RemoveToxicityOffset(val); } public final function CalculatePotionDuration(item : SItemUniqueId, isMutagenPotion : bool, optional itemName : name) : float { var duration, skillPassiveMod, mutagenSkillMod : float; var val, min, max : SAbilityAttributeValue; if(inv.IsIdValid(item)) { duration = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'duration')); } else { theGame.GetDefinitionsManager().GetItemAttributeValueNoRandom(itemName, true, 'duration', min, max); duration = CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); } skillPassiveMod = CalculateAttributeValue(GetAttributeValue('potion_duration')); if(isMutagenPotion && CanUseSkill(S_Alchemy_s14)) { val = GetSkillAttributeValue(S_Alchemy_s14, 'duration', false, true); mutagenSkillMod = val.valueMultiplicative * GetSkillLevel(S_Alchemy_s14); } duration = duration * (1 + skillPassiveMod + mutagenSkillMod); return duration; } public function ToxicityLowEnoughToDrinkPotion( slotid : EEquipmentSlots, optional itemId : SItemUniqueId ) : bool { var item : SItemUniqueId; var maxTox : float; var potionToxicity : float; var toxicityOffset : float; var effectType : EEffectType; var customAbilityName : name; if(itemId != GetInvalidUniqueId()) item = itemId; else item = itemSlots[slotid]; inv.GetPotionItemBuffData(item, effectType, customAbilityName); maxTox = abilityManager.GetStatMax(BCS_Toxicity); potionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity')); toxicityOffset = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity_offset')); if(effectType != EET_WhiteHoney) { if(abilityManager.GetStat(BCS_Toxicity, false) + potionToxicity + toxicityOffset > maxTox ) { return false; } } return true; } public final function HasFreeToxicityToDrinkPotion( item : SItemUniqueId, effectType : EEffectType, out finalPotionToxicity : float ) : bool { var i : int; var maxTox, toxicityOffset, adrenaline : float; var costReduction : SAbilityAttributeValue; if( effectType == EET_WhiteHoney ) { return true; } maxTox = abilityManager.GetStatMax(BCS_Toxicity); finalPotionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity')); toxicityOffset = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity_offset')); if(CanUseSkill(S_Perk_13)) { costReduction = GetSkillAttributeValue(S_Perk_13, 'cost_reduction', false, true); adrenaline = FloorF(GetStat(BCS_Focus)); costReduction = costReduction * adrenaline; finalPotionToxicity = (finalPotionToxicity - costReduction.valueBase) * (1 - costReduction.valueMultiplicative) - costReduction.valueAdditive; finalPotionToxicity = MaxF(0.f, finalPotionToxicity); } if(abilityManager.GetStat(BCS_Toxicity, false) + finalPotionToxicity + toxicityOffset > maxTox ) { return false; } return true; } public function DrinkPreparedPotion( slotid : EEquipmentSlots, optional itemId : SItemUniqueId ) { var potParams : W3PotionParams; var potionParams : SCustomEffectParams; var factPotionParams : W3Potion_Fact_Params; var adrenaline, hpGainValue, duration, finalPotionToxicity : float; var ret : EEffectInteract; var effectType : EEffectType; var item : SItemUniqueId; var customAbilityName, factId : name; var atts : array; var i : int; var mutagenParams : W3MutagenBuffCustomParams; if(itemId != GetInvalidUniqueId()) item = itemId; else item = itemSlots[slotid]; if(!inv.IsIdValid(item)) return; if( inv.SingletonItemGetAmmo(item) == 0 ) return; inv.GetPotionItemBuffData(item, effectType, customAbilityName); if( !HasFreeToxicityToDrinkPotion( item, effectType, finalPotionToxicity ) ) { return; } if(effectType == EET_Fact) { inv.GetItemAttributes(item, atts); for(i=0; i { if(StrBeginsWith(NameToString(atts[i]), "fact_")) { factId = atts[i]; break; } } factPotionParams = new W3Potion_Fact_Params in theGame; factPotionParams.factName = factId; factPotionParams.potionItemName = inv.GetItemName(item); potionParams.buffSpecificParams = factPotionParams; } else if(inv.ItemHasTag( item, 'Mutagen' )) { mutagenParams = new W3MutagenBuffCustomParams in theGame; mutagenParams.toxicityOffset = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity_offset')); mutagenParams.potionItemName = inv.GetItemName(item); potionParams.buffSpecificParams = mutagenParams; if( IsMutationActive( EPMT_Mutation10 ) && !HasBuff( EET_Mutation10 ) ) { AddEffectDefault( EET_Mutation10, this, "Mutation 10" ); } } else { potParams = new W3PotionParams in theGame; potParams.potionItemName = inv.GetItemName(item); potionParams.buffSpecificParams = potParams; } duration = CalculatePotionDuration(item, inv.ItemHasTag( item, 'Mutagen' )); potionParams.effectType = effectType; potionParams.creator = this; potionParams.sourceName = "drank_potion"; potionParams.duration = duration; potionParams.customAbilityName = customAbilityName; ret = AddEffectCustom(potionParams); if(factPotionParams) delete factPotionParams; if(mutagenParams) delete mutagenParams; inv.SingletonItemRemoveAmmo(item); if(ret == EI_Pass || ret == EI_Override || ret == EI_Cumulate) { if( finalPotionToxicity > 0.f ) { abilityManager.GainStat(BCS_Toxicity, finalPotionToxicity ); } if(CanUseSkill(S_Perk_13)) { abilityManager.DrainFocus(adrenaline); } if (!IsEffectActive('invisible')) { PlayEffect('use_potion'); } if ( inv.ItemHasTag( item, 'Mutagen' ) ) { theGame.GetGamerProfile().CheckTrialOfGrasses(); SetFailedFundamentalsFirstAchievementCondition(true); } if(CanUseSkill(S_Alchemy_s02)) { hpGainValue = ClampF(GetStatMax(BCS_Vitality) * CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s02, 'vitality_gain_perc', false, true)) * GetSkillLevel(S_Alchemy_s02), 0, GetStatMax(BCS_Vitality)); GainStat(BCS_Vitality, hpGainValue); } if(CanUseSkill(S_Alchemy_s04) && !skillBonusPotionEffect && (RandF() < CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s04, 'apply_chance', false, true)) * GetSkillLevel(S_Alchemy_s04))) { AddRandomPotionEffectFromAlch4Skill( effectType ); } theGame.GetGamerProfile().SetStat(ES_ActivePotions, effectManager.GetPotionBuffsCount()); } theTelemetry.LogWithLabel(TE_ELIXIR_USED, inv.GetItemName(item)); if(ShouldProcessTutorial('TutorialPotionAmmo')) { FactsAdd("tut_used_potion"); } SetFailedFundamentalsFirstAchievementCondition(true); } private final function AddRandomPotionEffectFromAlch4Skill( currentlyDrankPotion : EEffectType ) { var randomPotions : array; var currentPotion : CBaseGameplayEffect; var effectsOld, effectsNew : array; var i, ind : int; var duration : float; var params : SCustomEffectParams; var ret : EEffectInteract; randomPotions.PushBack( EET_BlackBlood ); randomPotions.PushBack( EET_Blizzard ); randomPotions.PushBack( EET_FullMoon ); randomPotions.PushBack( EET_GoldenOriole ); randomPotions.PushBack( EET_KillerWhale ); randomPotions.PushBack( EET_MariborForest ); randomPotions.PushBack( EET_PetriPhiltre ); randomPotions.PushBack( EET_Swallow ); randomPotions.PushBack( EET_TawnyOwl ); randomPotions.PushBack( EET_Thunderbolt ); randomPotions.Remove( currentlyDrankPotion ); ind = RandRange( randomPotions.Size() ); if( HasBuff( randomPotions[ ind ] ) ) { currentPotion = GetBuff( randomPotions[ ind ] ); currentPotion.SetTimeLeft( currentPotion.GetInitialDurationAfterResists() ); } else { duration = BonusPotionGetDurationFromXML( randomPotions[ ind ] ); if(duration > 0) { effectsOld = GetCurrentEffects(); params.effectType = randomPotions[ ind ]; params.creator = this; params.sourceName = SkillEnumToName( S_Alchemy_s04 ); params.duration = duration; ret = AddEffectCustom( params ); if( ret != EI_Undefined && ret != EI_Deny ) { effectsNew = GetCurrentEffects(); ind = -1; for( i=effectsNew.Size()-1; i>=0; i-=1) { if( !effectsOld.Contains( effectsNew[i] ) ) { ind = i; break; } } if(ind > -1) { skillBonusPotionEffect = effectsNew[ind]; } } } } } private function BonusPotionGetDurationFromXML(type : EEffectType) : float { var dm : CDefinitionsManagerAccessor; var main, ingredients : SCustomNode; var tmpName, typeName, itemName : name; var abs : array; var min, max : SAbilityAttributeValue; var tmpInt : int; var temp : array; var i, temp2, temp3 : int; dm = theGame.GetDefinitionsManager(); main = dm.GetCustomDefinition('alchemy_recipes'); typeName = EffectTypeToName(type); for(i=0; i { if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'type_name', tmpName)) { if(tmpName == typeName) { if(dm.GetCustomNodeAttributeValueInt(main.subNodes[i], 'level', tmpInt)) { if(tmpInt == 1) { if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'cookedItem_name', itemName)) { if(IsNameValid(itemName)) { break; } } } } } } } if(!IsNameValid(itemName)) return 0; dm.GetItemAbilitiesWithWeights(itemName, true, abs, temp, temp2, temp3); dm.GetAbilitiesAttributeValue(abs, 'duration', min, max); return CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); } public function ClearSkillBonusPotionEffect() { skillBonusPotionEffect = NULL; } public function GetSkillBonusPotionEffect() : CBaseGameplayEffect { return skillBonusPotionEffect; } public final function HasRunewordActive(abilityName : name) : bool { var item : SItemUniqueId; var hasRuneword : bool; if(GetItemEquippedOnSlot(EES_SteelSword, item)) { hasRuneword = inv.ItemHasAbility(item, abilityName); } if(!hasRuneword) { if(GetItemEquippedOnSlot(EES_SilverSword, item)) { hasRuneword = inv.ItemHasAbility(item, abilityName); } } return hasRuneword; } public final function GetShrineBuffs() : array { var null : array; if(effectManager && effectManager.IsReady()) return effectManager.GetShrineBuffs(); return null; } public final function AddRepairObjectBuff(armor : bool, weapon : bool) : bool { var added : bool; added = false; if(weapon && (IsAnyItemEquippedOnSlot(EES_SilverSword) || IsAnyItemEquippedOnSlot(EES_SteelSword)) ) { AddEffectDefault(EET_EnhancedWeapon, this, "repair_object", false); added = true; } if(armor && (IsAnyItemEquippedOnSlot(EES_Armor) || IsAnyItemEquippedOnSlot(EES_Gloves) || IsAnyItemEquippedOnSlot(EES_Boots) || IsAnyItemEquippedOnSlot(EES_Pants)) ) { AddEffectDefault(EET_EnhancedArmor, this, "repair_object", false); added = true; } return added; } public function StartCSAnim(buff : CBaseGameplayEffect) : bool { if(IsAnyQuenActive() && (W3CriticalDOTEffect)buff) return false; return super.StartCSAnim(buff); } public function GetPotionBuffLevel(effectType : EEffectType) : int { if(effectManager && effectManager.IsReady()) return effectManager.GetPotionBuffLevel(effectType); return 0; } event OnLevelGained(currentLevel : int, show : bool) { var i : int; // Added this var itemN : array; // Added this var isArmor : bool; var isOther : bool; var addArmor : bool; var itemLevel : int; var hud : CR4ScriptedHud; hud = (CR4ScriptedHud)theGame.GetHud(); inv = thePlayer.GetInventory(); inv.GetAllItems(itemN); // Added this for( i = 0; i < itemN.Size(); i += 1 ) // added this (Loops through every item in your inventory) { isArmor = false; isOther = false; addArmor = true; if (thePlayer.inv.ItemHasTag(itemN[i], 'dlcArmor1') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcArmor2')) { isArmor = true; } else if (thePlayer.inv.ItemHasTag(itemN[i], 'dlcPants1') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcPants2') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcGloves1') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcGloves2') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcBoots1') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcBoots2') ) { isOther = true; } if( thePlayer.inv.ItemHasTag(itemN[i], 'ArmorMod') || thePlayer.inv.ItemHasTag(itemN[i], 'dlcModArmor') ) // Only ArmorMod items in your inventory { theGame.GameplayFactsSet("SignMod", 0); itemLevel = thePlayer.GetInventory().GetItemLevel(itemN[i]); // Makes sure the Item Level is Re-Set on level up if(isArmor || isOther) { if(itemLevel > thePlayer.GetLevel()) { addArmor = false; } } if(addArmor) { thePlayer.GetInventory().GetItemArmorTotal(itemN[i], true); // Add the new Armor Rating } } } // End if(abilityManager && abilityManager.IsInitialized()) { ((W3PlayerAbilityManager)abilityManager).OnLevelGained(currentLevel); } if ( theGame.GetDifficultyMode() != EDM_Hardcore ) { Heal(GetStatMax(BCS_Vitality)); } if(currentLevel >= 35) { theGame.GetGamerProfile().AddAchievement(EA_Immortal); } if ( hud && currentLevel < levelManager.GetMaxLevel() && FactsQuerySum( "DebugNoLevelUpUpdates" ) == 0 ) { hud.OnLevelUpUpdate(currentLevel, show); } theGame.RequestAutoSave( "level gained", false ); } public function GetSignStats(skill : ESkill, out damageType : name, out damageVal : float, out spellPower : SAbilityAttributeValue) { var i, size : int; var dm : CDefinitionsManagerAccessor; var attrs : array; spellPower = GetPowerStatValue(CPS_SpellPower); dm = theGame.GetDefinitionsManager(); dm.GetAbilityAttributes(GetSkillAbilityName(skill), attrs); size = attrs.Size(); for( i = 0; i < size; i += 1 ) { if( IsDamageTypeNameValid(attrs[i]) ) { damageVal = CalculateAttributeValue(GetSkillAttributeValue(skill, attrs[i], false, true)); damageType = attrs[i]; break; } } } public function SetIgnorePainMaxVitality(val : float) { if(abilityManager && abilityManager.IsInitialized()) abilityManager.SetStatPointMax(BCS_Vitality, val); } event OnAnimEvent_ActionBlend( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( animEventType == AET_DurationStart && !disableActionBlend ) { if ( this.IsCastingSign() ) ProcessSignEvent( 'cast_end' ); FindMoveTarget(); SetCanPlayHitAnim( true ); this.SetBIsCombatActionAllowed( true ); if ( this.GetFinisherVictim() && this.GetFinisherVictim().HasAbility( 'ForceFinisher' ) && !isInFinisher ) { this.GetFinisherVictim().SignalGameplayEvent( 'Finisher' ); } else if (this.BufferCombatAction != EBAT_EMPTY ) { if ( !IsCombatMusicEnabled() ) { SetCombatActionHeading( ProcessCombatActionHeading( this.BufferCombatAction ) ); FindTarget(); UpdateDisplayTarget( true ); } if ( AllowAttack( GetTarget(), this.BufferCombatAction ) ) this.ProcessCombatActionBuffer(); } else { ResumeStaminaRegen( 'InsideCombatAction' ); } } else if ( disableActionBlend ) { disableActionBlend = false; } } event OnAnimEvent_Sign( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if( animEventType == AET_Tick ) { ProcessSignEvent( animEventName ); } } event OnAnimEvent_Throwable( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { var thrownEntity : CThrowable; thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle ); if ( inv.IsItemCrossbow( inv.GetItemFromSlot('l_weapon') ) && rangedWeapon.OnProcessThrowEvent( animEventName ) ) { return true; } else if( thrownEntity && IsThrowingItem() && thrownEntity.OnProcessThrowEvent( animEventName ) ) { return true; } } event OnTaskSyncAnim( npc : CNewNPC, animNameLeft : name ) { var tmpBool : bool; var tmpName : name; var damage, points, resistance : float; var min, max : SAbilityAttributeValue; var mc : EMonsterCategory; super.OnTaskSyncAnim( npc, animNameLeft ); if( animNameLeft == 'BruxaBite' && IsMutationActive( EPMT_Mutation4 ) ) { theGame.GetMonsterParamsForActor( npc, mc, tmpName, tmpBool, tmpBool, tmpBool ); if( mc == MC_Vampire ) { GetResistValue( CDS_BleedingRes, points, resistance ); theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'BleedingEffect', 'DirectDamage', min, max ); damage = MaxF( 0.f, max.valueMultiplicative * GetMaxHealth() - points ); theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'BleedingEffect', 'duration', min, max ); damage *= min.valueAdditive * ( 1 - MinF( 1.f, resistance ) ); if( damage > 0.f ) { npc.AddAbility( 'Mutation4BloodDebuff' ); ProcessActionMutation4ReturnedDamage( damage, npc, EAHA_ForceNo ); npc.AddTimer( 'RemoveMutation4BloodDebuff', 15.f, , , , , true ); } } } } public function ProcessActionMutation4ReturnedDamage( damageDealt : float, attacker : CActor, hitAnimationType : EActionHitAnim, optional action : W3DamageAction ) : bool { var customParams : SCustomEffectParams; var currToxicity : float; var min, max, customDamageValue : SAbilityAttributeValue; var dm : CDefinitionsManagerAccessor; var animAction : W3DamageAction; if( damageDealt <= 0 ) { return false; } if( action ) { action.SetMutation4Triggered(); } dm = theGame.GetDefinitionsManager(); currToxicity = GetStat( BCS_Toxicity ); dm.GetAbilityAttributeValue( 'AcidEffect', 'DirectDamage', min, max ); customDamageValue.valueAdditive = damageDealt * min.valueAdditive; if( currToxicity > 0 ) { customDamageValue.valueAdditive *= currToxicity; } dm.GetAbilityAttributeValue( 'AcidEffect', 'duration', min, max ); customDamageValue.valueAdditive /= min.valueAdditive; customParams.effectType = EET_Acid; customParams.effectValue = customDamageValue; customParams.duration = min.valueAdditive; customParams.creator = this; customParams.sourceName = 'Mutation4'; attacker.AddEffectCustom( customParams ); animAction = new W3DamageAction in theGame; animAction.Initialize( this, attacker, NULL, 'Mutation4', EHRT_Reflect, CPS_Undefined, true, false, false, false ); animAction.SetCannotReturnDamage( true ); animAction.SetCanPlayHitParticle( false ); animAction.SetHitAnimationPlayType( hitAnimationType ); theGame.damageMgr.ProcessAction( animAction ); delete animAction; theGame.MutationHUDFeedback( MFT_PlayOnce ); return true; } event OnPlayerActionEnd() { var l_i : int; var l_bed : W3WitcherBed; l_i = (int)GetBehaviorVariable( 'playerExplorationAction' ); if( l_i == PEA_GoToSleep ) { l_bed = (W3WitcherBed)theGame.GetEntityByTag( 'witcherBed' ); BlockAllActions( 'WitcherBed', false ); l_bed.ApplyAppearance( "collision" ); l_bed.GotoState( 'WakeUp' ); theGame.ReleaseNoSaveLock( l_bed.m_bedSaveLock ); substateManager.m_MovementCorrectorO.disallowRotWhenGoingToSleep = false; } super.OnPlayerActionEnd(); } event OnPlayerActionStartFinished() { var l_initData : W3SingleMenuInitData; var l_i : int; l_i = (int)GetBehaviorVariable( 'playerExplorationAction' ); if( l_i == PEA_GoToSleep ) { l_initData = new W3SingleMenuInitData in this; l_initData.SetBlockOtherPanels( true ); l_initData.ignoreSaveSystem = true; l_initData.ignoreMeditationCheck = true; l_initData.setDefaultState( '' ); l_initData.isBonusMeditationAvailable = true; l_initData.fixedMenuName = 'MeditationClockMenu'; theGame.RequestMenuWithBackground( 'MeditationClockMenu', 'CommonMenu', l_initData ); } super.OnPlayerActionStartFinished(); } public function IsInCombatAction_SpecialAttack() : bool { if ( IsInCombatAction() && ( GetCombatAction() == EBAT_SpecialAttack_Light || GetCombatAction() == EBAT_SpecialAttack_Heavy ) ) return true; else return false; } public function IsInCombatAction_SpecialAttackHeavy() : bool { if ( IsInCombatAction() && GetCombatAction() == EBAT_SpecialAttack_Heavy ) return true; else return false; } protected function WhenCombatActionIsFinished() { super.WhenCombatActionIsFinished(); RemoveTimer( 'ProcessAttackTimer' ); RemoveTimer( 'AttackTimerEnd' ); CastSignAbort(); specialAttackCamera = false; this.OnPerformSpecialAttack( true, false ); } event OnCombatActionEnd() { this.CleanCombatActionBuffer(); super.OnCombatActionEnd(); RemoveTemporarySkills(); } event OnCombatActionFriendlyEnd() { if ( IsCastingSign() ) { SetBehaviorVariable( 'IsCastingSign', 0 ); SetCurrentlyCastSign( ST_None, NULL ); LogChannel( 'ST_None', "ST_None" ); } super.OnCombatActionFriendlyEnd(); } public function GetPowerStatValue( stat : ECharacterPowerStats, optional ablName : name, optional ignoreDeath : bool ) : SAbilityAttributeValue { var result : SAbilityAttributeValue; result = super.GetPowerStatValue( stat, ablName, ignoreDeath ); ApplyMutation10StatBoost( result ); return result; } timer function OpenRadialMenu( time: float, id : int ) { if( GetBIsCombatActionAllowed() && !IsUITakeInput() ) { bShowRadialMenu = true; } this.RemoveTimer('OpenRadialMenu'); } public function OnAddRadialMenuOpenTimer( ) { this.AddTimer('OpenRadialMenu', _HoldBeforeOpenRadialMenuTime * theGame.GetTimeScale() ); } public function SetShowRadialMenuOpenFlag( bSet : bool ) { bShowRadialMenu = bSet; } public function OnRemoveRadialMenuOpenTimer() { this.RemoveTimer('OpenRadialMenu'); } public function ResetRadialMenuOpenTimer() { this.RemoveTimer('OpenRadialMenu'); if( GetBIsCombatActionAllowed() ) { AddTimer('OpenRadialMenu', _HoldBeforeOpenRadialMenuTime * theGame.GetTimeScale() ); } } timer function ResendCompanionDisplayName(dt : float, id : int) { var hud : CR4ScriptedHud; var companionModule : CR4HudModuleCompanion; hud = (CR4ScriptedHud)theGame.GetHud(); if( hud ) { companionModule = (CR4HudModuleCompanion)hud.GetHudModule("CompanionModule"); if( companionModule ) { companionModule.ResendDisplayName(); } } } timer function ResendCompanionDisplayNameSecond(dt : float, id : int) { var hud : CR4ScriptedHud; var companionModule : CR4HudModuleCompanion; hud = (CR4ScriptedHud)theGame.GetHud(); if( hud ) { companionModule = (CR4HudModuleCompanion)hud.GetHudModule("CompanionModule"); if( companionModule ) { companionModule.ResendDisplayNameSecond(); } } } public function RemoveCompanionDisplayNameTimer() { this.RemoveTimer('ResendCompanionDisplayName'); } public function RemoveCompanionDisplayNameTimerSecond() { this.RemoveTimer('ResendCompanionDisplayNameSecond'); } public function GetCompanionNPCTag() : name { return companionNPCTag; } public function SetCompanionNPCTag( value : name ) { companionNPCTag = value; } public function GetCompanionNPCTag2() : name { return companionNPCTag2; } public function SetCompanionNPCTag2( value : name ) { companionNPCTag2 = value; } public function GetCompanionNPCIconPath() : string { return companionNPCIconPath; } public function SetCompanionNPCIconPath( value : string ) { companionNPCIconPath = value; } public function GetCompanionNPCIconPath2() : string { return companionNPCIconPath2; } public function SetCompanionNPCIconPath2( value : string ) { companionNPCIconPath2 = value; } public function ReactToBeingHit(damageAction : W3DamageAction, optional buffNotApplied : bool) : bool { var chance : float; var procQuen : W3SignEntity; if(!damageAction.IsDoTDamage() && damageAction.DealsAnyDamage()) { if(inv.IsItemBomb(selectedItemId)) { BombThrowAbort(); } else { ThrowingAbort(); } } if(damageAction.IsActionRanged()) { chance = CalculateAttributeValue(GetAttributeValue('quen_chance_on_projectile')); if(chance > 0) { chance = ClampF(chance, 0, 1); if(RandF() < chance) { procQuen = (W3SignEntity)theGame.CreateEntity(signs[ST_Quen].template, GetWorldPosition(), GetWorldRotation() ); procQuen.Init(signOwner, signs[ST_Quen].entity, true ); procQuen.OnStarted(); procQuen.OnThrowing(); procQuen.OnEnded(); } } } if( !((W3Effect_Toxicity)damageAction.causer) ) MeditationForceAbort(true); if(IsDoingSpecialAttack(false)) damageAction.SetHitAnimationPlayType(EAHA_ForceNo); return super.ReactToBeingHit(damageAction, buffNotApplied); } protected function ShouldPauseHealthRegenOnHit() : bool { if( ( HasBuff( EET_Swallow ) && GetPotionBuffLevel( EET_Swallow ) >= 3 ) || HasBuff( EET_Runeword8 ) || HasBuff( EET_Mutation11Buff ) ) { return false; } return true; } public function SetMappinToHighlight( mappinName : name, mappinState : bool ) { var mappinDef : SHighlightMappin; mappinDef.MappinName = mappinName; mappinDef.MappinState = mappinState; MappinToHighlight.PushBack(mappinDef); } public function ClearMappinToHighlight() { MappinToHighlight.Clear(); } public function CastSignAbort() { if( currentlyCastSign != ST_None && signs[currentlyCastSign].entity) { signs[currentlyCastSign].entity.OnSignAborted(); } } event OnBlockingSceneStarted( scene: CStoryScene ) { var med : W3PlayerWitcherStateMeditationWaiting; med = (W3PlayerWitcherStateMeditationWaiting)GetCurrentState(); if(med) { med.StopRequested(true); } super.OnBlockingSceneStarted( scene ); } public function GetHorseManager() : W3HorseManager { return (W3HorseManager)EntityHandleGet( horseManagerHandle ); } public function HorseEquipItem(horsesItemId : SItemUniqueId) : bool { var man : W3HorseManager; man = GetHorseManager(); if(man) return man.EquipItem(horsesItemId) != GetInvalidUniqueId(); return false; } public function HorseUnequipItem(slot : EEquipmentSlots) : bool { var man : W3HorseManager; man = GetHorseManager(); if(man) return man.UnequipItem(slot) != GetInvalidUniqueId(); return false; } public final function HorseRemoveItemByName(itemName : name, quantity : int) { var man : W3HorseManager; man = GetHorseManager(); if(man) man.HorseRemoveItemByName(itemName, quantity); } public final function HorseRemoveItemByCategory(itemCategory : name, quantity : int) { var man : W3HorseManager; man = GetHorseManager(); if(man) man.HorseRemoveItemByCategory(itemCategory, quantity); } public final function HorseRemoveItemByTag(itemTag : name, quantity : int) { var man : W3HorseManager; man = GetHorseManager(); if(man) man.HorseRemoveItemByTag(itemTag, quantity); } public function GetAssociatedInventory() : CInventoryComponent { var man : W3HorseManager; man = GetHorseManager(); if(man) return man.GetInventoryComponent(); return NULL; } public final function TutorialMutagensUnequipPlayerSkills() : array { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; return pam.TutorialMutagensUnequipPlayerSkills(); } public final function TutorialMutagensEquipOneGoodSkill() { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; pam.TutorialMutagensEquipOneGoodSkill(); } public final function TutorialMutagensEquipOneGoodOneBadSkill() { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; if(pam) pam.TutorialMutagensEquipOneGoodOneBadSkill(); } public final function TutorialMutagensEquipThreeGoodSkills() { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; if(pam) pam.TutorialMutagensEquipThreeGoodSkills(); } public final function TutorialMutagensCleanupTempSkills(savedEquippedSkills : array) { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; return pam.TutorialMutagensCleanupTempSkills(savedEquippedSkills); } public final function CalculatedArmorStaminaRegenBonus() : float { var armorEq, glovesEq, pantsEq, bootsEq : bool; var tempItem : SItemUniqueId; var staminaRegenVal : float; var armorRegenVal : SAbilityAttributeValue; if( HasAbility( 'Glyphword 2 _Stats', true ) ) { armorEq = inv.GetItemEquippedOnSlot( EES_Armor, tempItem ); glovesEq = inv.GetItemEquippedOnSlot( EES_Gloves, tempItem ); pantsEq = inv.GetItemEquippedOnSlot( EES_Pants, tempItem ); bootsEq = inv.GetItemEquippedOnSlot( EES_Boots, tempItem ); if ( armorEq ) staminaRegenVal += 0.1; if ( glovesEq ) staminaRegenVal += 0.02; if ( pantsEq ) staminaRegenVal += 0.1; if ( bootsEq ) staminaRegenVal += 0.03; } else if( HasAbility( 'Glyphword 3 _Stats', true ) ) { staminaRegenVal = 0; } else if( HasAbility( 'Glyphword 4 _Stats', true ) ) { armorEq = inv.GetItemEquippedOnSlot( EES_Armor, tempItem ); glovesEq = inv.GetItemEquippedOnSlot( EES_Gloves, tempItem ); pantsEq = inv.GetItemEquippedOnSlot( EES_Pants, tempItem ); bootsEq = inv.GetItemEquippedOnSlot( EES_Boots, tempItem ); if ( armorEq ) staminaRegenVal -= 0.1; if ( glovesEq ) staminaRegenVal -= 0.02; if ( pantsEq ) staminaRegenVal -= 0.1; if ( bootsEq ) staminaRegenVal -= 0.03; } else { armorRegenVal = GetAttributeValue('staminaRegen_armor_mod'); staminaRegenVal = armorRegenVal.valueMultiplicative; } return staminaRegenVal; } public function GetOffenseStatsList( optional hackMode : int ) : SPlayerOffenseStats { var playerOffenseStats:SPlayerOffenseStats; var steelDmg, silverDmg, elementalSteel, elementalSilver : float; var steelCritChance, steelCritDmg : float; var silverCritChance, silverCritDmg : float; var attackPower : SAbilityAttributeValue; var fastCritChance, fastCritDmg : float; var strongCritChance, strongCritDmg : float; var fastAP, strongAP, min, max : SAbilityAttributeValue; var item, crossbow : SItemUniqueId; var value : SAbilityAttributeValue; var mutagen : CBaseGameplayEffect; var thunder : W3Potion_Thunderbolt; if(!abilityManager || !abilityManager.IsInitialized()) return playerOffenseStats; if (CanUseSkill(S_Sword_s21)) fastAP += GetSkillAttributeValue(S_Sword_s21, PowerStatEnumToName(CPS_AttackPower), false, true) * GetSkillLevel(S_Sword_s21); if (CanUseSkill(S_Perk_05)) { fastAP += GetAttributeValue('attack_power_fast_style'); fastCritDmg += CalculateAttributeValue(GetAttributeValue('critical_hit_chance_fast_style')); strongCritDmg += CalculateAttributeValue(GetAttributeValue('critical_hit_chance_fast_style')); } if (CanUseSkill(S_Sword_s04)) strongAP += GetSkillAttributeValue(S_Sword_s04, PowerStatEnumToName(CPS_AttackPower), false, true) * GetSkillLevel(S_Sword_s04); if (CanUseSkill(S_Perk_07)) strongAP += GetAttributeValue('attack_power_heavy_style'); if (CanUseSkill(S_Sword_s17)) { fastCritChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s17, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s17); fastCritDmg += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s17, theGame.params.CRITICAL_HIT_DAMAGE_BONUS, false, true)) * GetSkillLevel(S_Sword_s17); } if (CanUseSkill(S_Sword_s08)) { strongCritChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s08, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s08); strongCritDmg += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s08, theGame.params.CRITICAL_HIT_DAMAGE_BONUS, false, true)) * GetSkillLevel(S_Sword_s08); } if ( HasBuff(EET_Mutagen05) && (GetStat(BCS_Vitality) == GetStatMax(BCS_Vitality)) ) { attackPower += GetAttributeValue('damageIncrease'); } steelCritChance += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_CHANCE)); silverCritChance += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_CHANCE)); steelCritDmg += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); silverCritDmg += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); attackPower += GetPowerStatValue(CPS_AttackPower); if (GetItemEquippedOnSlot(EES_SteelSword, item)) { steelDmg = GetTotalWeaponDamage(item, theGame.params.DAMAGE_NAME_SLASHING, GetInvalidUniqueId()); steelDmg += GetTotalWeaponDamage(item, theGame.params.DAMAGE_NAME_PIERCING, GetInvalidUniqueId()); steelDmg += GetTotalWeaponDamage(item, theGame.params.DAMAGE_NAME_BLUDGEONING, GetInvalidUniqueId()); elementalSteel = CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_FIRE)); elementalSteel += CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_FROST)); if ( GetInventory().IsItemHeld(item) ) { steelCritChance -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_CHANCE)); silverCritChance -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_CHANCE)); steelCritDmg -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); silverCritDmg -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); } steelCritChance += CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_CHANCE)); steelCritDmg += CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); thunder = (W3Potion_Thunderbolt)GetBuff(EET_Thunderbolt); if(thunder && thunder.GetBuffLevel() == 3 && GetCurWeather() == EWE_Storm) { steelCritChance += 1.0f; } } else { steelDmg += 0; steelCritChance += 0; steelCritDmg +=0; } if (GetItemEquippedOnSlot(EES_SilverSword, item)) { silverDmg = GetTotalWeaponDamage(item, theGame.params.DAMAGE_NAME_SILVER, GetInvalidUniqueId()); elementalSilver = CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_FIRE)); elementalSilver += CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_FROST)); if ( GetInventory().IsItemHeld(item) ) { steelCritChance -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_CHANCE)); silverCritChance -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_CHANCE)); steelCritDmg -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); silverCritDmg -= CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); } silverCritChance += CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_CHANCE)); silverCritDmg += CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.CRITICAL_HIT_DAMAGE_BONUS)); thunder = (W3Potion_Thunderbolt)GetBuff(EET_Thunderbolt); if(thunder && thunder.GetBuffLevel() == 3 && GetCurWeather() == EWE_Storm) { silverCritChance += 1.0f; } } else { silverDmg += 0; silverCritChance += 0; silverCritDmg +=0; } if ( HasAbility('Runeword 4 _Stats', true) ) { steelDmg += steelDmg * (abilityManager.GetOverhealBonus() / GetStatMax(BCS_Vitality)); silverDmg += silverDmg * (abilityManager.GetOverhealBonus() / GetStatMax(BCS_Vitality)); } fastAP += attackPower; strongAP += attackPower; playerOffenseStats.steelFastCritChance = (steelCritChance + fastCritChance) * 100; playerOffenseStats.steelFastCritDmg = steelCritDmg + fastCritDmg; if ( steelDmg != 0 ) { playerOffenseStats.steelFastDmg = (steelDmg + fastAP.valueBase) * fastAP.valueMultiplicative + fastAP.valueAdditive + elementalSteel; playerOffenseStats.steelFastCritDmg = (steelDmg + fastAP.valueBase) * (fastAP.valueMultiplicative + playerOffenseStats.steelFastCritDmg) + fastAP.valueAdditive + elementalSteel; } else { playerOffenseStats.steelFastDmg = 0; playerOffenseStats.steelFastCritDmg = 0; } playerOffenseStats.steelFastDPS = (playerOffenseStats.steelFastDmg * (100 - playerOffenseStats.steelFastCritChance) + playerOffenseStats.steelFastCritDmg * playerOffenseStats.steelFastCritChance) / 100; playerOffenseStats.steelFastDPS = playerOffenseStats.steelFastDPS / 0.6; playerOffenseStats.steelStrongCritChance = (steelCritChance + strongCritChance) * 100; playerOffenseStats.steelStrongCritDmg = steelCritDmg + strongCritDmg; if ( steelDmg != 0 ) { playerOffenseStats.steelStrongDmg = (steelDmg + strongAP.valueBase) * strongAP.valueMultiplicative + strongAP.valueAdditive + elementalSteel; playerOffenseStats.steelStrongDmg *= 1.833f; playerOffenseStats.steelStrongCritDmg = (steelDmg + strongAP.valueBase) * (strongAP.valueMultiplicative + playerOffenseStats.steelStrongCritDmg) + strongAP.valueAdditive + elementalSteel; playerOffenseStats.steelStrongCritDmg *= 1.833f; } else { playerOffenseStats.steelStrongDmg = 0; playerOffenseStats.steelStrongCritDmg = 0; } playerOffenseStats.steelStrongDPS = (playerOffenseStats.steelStrongDmg * (100 - playerOffenseStats.steelStrongCritChance) + playerOffenseStats.steelStrongCritDmg * playerOffenseStats.steelStrongCritChance) / 100; playerOffenseStats.steelStrongDPS = playerOffenseStats.steelStrongDPS / 1.1; playerOffenseStats.silverFastCritChance = (silverCritChance + fastCritChance) * 100; playerOffenseStats.silverFastCritDmg = silverCritDmg + fastCritDmg; if ( silverDmg != 0 ) { playerOffenseStats.silverFastDmg = (silverDmg + fastAP.valueBase) * fastAP.valueMultiplicative + fastAP.valueAdditive + elementalSilver; playerOffenseStats.silverFastCritDmg = (silverDmg + fastAP.valueBase) * (fastAP.valueMultiplicative + playerOffenseStats.silverFastCritDmg) + fastAP.valueAdditive + elementalSilver; } else { playerOffenseStats.silverFastDmg = 0; playerOffenseStats.silverFastCritDmg = 0; } playerOffenseStats.silverFastDPS = (playerOffenseStats.silverFastDmg * (100 - playerOffenseStats.silverFastCritChance) + playerOffenseStats.silverFastCritDmg * playerOffenseStats.silverFastCritChance) / 100; playerOffenseStats.silverFastDPS = playerOffenseStats.silverFastDPS / 0.6; playerOffenseStats.silverStrongCritChance = (silverCritChance + strongCritChance) * 100; playerOffenseStats.silverStrongCritDmg = silverCritDmg + strongCritDmg; if ( silverDmg != 0 ) { playerOffenseStats.silverStrongDmg = (silverDmg + strongAP.valueBase) * strongAP.valueMultiplicative + strongAP.valueAdditive + elementalSilver; playerOffenseStats.silverStrongDmg *= 1.833f; playerOffenseStats.silverStrongCritDmg = (silverDmg + strongAP.valueBase) * (strongAP.valueMultiplicative + playerOffenseStats.silverStrongCritDmg) + strongAP.valueAdditive + elementalSilver; playerOffenseStats.silverStrongCritDmg *= 1.833f; } else { playerOffenseStats.silverStrongDmg = 0; playerOffenseStats.silverStrongCritDmg = 0; } playerOffenseStats.silverStrongDPS = (playerOffenseStats.silverStrongDmg * (100 - playerOffenseStats.silverStrongCritChance) + playerOffenseStats.silverStrongCritDmg * playerOffenseStats.silverStrongCritChance) / 100; playerOffenseStats.silverStrongDPS = playerOffenseStats.silverStrongDPS / 1.1; playerOffenseStats.crossbowCritChance = GetCriticalHitChance( false, false, NULL, MC_NotSet, true ); playerOffenseStats.crossbowSteelDmgType = theGame.params.DAMAGE_NAME_PIERCING; if (GetItemEquippedOnSlot(EES_Bolt, item)) { steelDmg = CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_FIRE)); if(steelDmg > 0) { playerOffenseStats.crossbowSteelDmg = steelDmg; playerOffenseStats.crossbowSteelDmgType = theGame.params.DAMAGE_NAME_FIRE; playerOffenseStats.crossbowSilverDmg = steelDmg; } else { playerOffenseStats.crossbowSilverDmg = CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_SILVER)); steelDmg = CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_PIERCING)); if(steelDmg > 0) { playerOffenseStats.crossbowSteelDmg = steelDmg; playerOffenseStats.crossbowSteelDmgType = theGame.params.DAMAGE_NAME_PIERCING; } else { playerOffenseStats.crossbowSteelDmg = CalculateAttributeValue(GetInventory().GetItemAttributeValue(item, theGame.params.DAMAGE_NAME_BLUDGEONING)); playerOffenseStats.crossbowSteelDmgType = theGame.params.DAMAGE_NAME_BLUDGEONING; } } } if (GetItemEquippedOnSlot(EES_RangedWeapon, item)) { attackPower += GetInventory().GetItemAttributeValue(item, PowerStatEnumToName(CPS_AttackPower)); if(CanUseSkill(S_Perk_02)) { attackPower += GetSkillAttributeValue(S_Perk_02, PowerStatEnumToName(CPS_AttackPower), false, true); } if( hackMode != 1 && ( IsMutationActive( EPMT_Mutation9 ) || hackMode == 2 ) ) { theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Mutation9', 'damage', min, max ); playerOffenseStats.crossbowSteelDmg += min.valueAdditive; playerOffenseStats.crossbowSilverDmg += min.valueAdditive; } playerOffenseStats.crossbowSteelDmg = (playerOffenseStats.crossbowSteelDmg + attackPower.valueBase) * attackPower.valueMultiplicative + attackPower.valueAdditive; playerOffenseStats.crossbowSilverDmg = (playerOffenseStats.crossbowSilverDmg + attackPower.valueBase) * attackPower.valueMultiplicative + attackPower.valueAdditive; } else { playerOffenseStats.crossbowSteelDmg = 0; playerOffenseStats.crossbowSilverDmg = 0; playerOffenseStats.crossbowSteelDmgType = theGame.params.DAMAGE_NAME_PIERCING; } return playerOffenseStats; } public function GetTotalWeaponDamage(weaponId : SItemUniqueId, damageTypeName : name, crossbowId : SItemUniqueId) : float { var damage, durRatio, durMod, itemMod : float; var repairObjectBonus, min, max : SAbilityAttributeValue; durMod = 0; damage = super.GetTotalWeaponDamage(weaponId, damageTypeName, crossbowId); if( IsMutationActive( EPMT_Mutation9 ) && inv.IsItemBolt( weaponId ) && IsDamageTypeAnyPhysicalType( damageTypeName ) ) { theGame.GetDefinitionsManager().GetAbilityAttributeValue('Mutation9', 'damage', min, max); damage += min.valueAdditive; } if(IsPhysicalResistStat(GetResistForDamage(damageTypeName, false))) { repairObjectBonus = inv.GetItemAttributeValue(weaponId, theGame.params.REPAIR_OBJECT_BONUS); durRatio = -1; if(inv.IsIdValid(crossbowId) && inv.HasItemDurability(crossbowId)) { durRatio = inv.GetItemDurabilityRatio(crossbowId); } else if(inv.IsIdValid(weaponId) && inv.HasItemDurability(weaponId)) { durRatio = inv.GetItemDurabilityRatio(weaponId); } if(durRatio >= 0) durMod = theGame.params.GetDurabilityMultiplier(durRatio, true); else durMod = 1; } if( damageTypeName == 'SilverDamage' && inv.ItemHasTag( weaponId, 'Aerondight' ) ) { itemMod = inv.GetItemModifierFloat( weaponId, 'PermDamageBoost' ); if( itemMod > 0.f ) { damage += itemMod; } } return damage * (durMod + repairObjectBonus.valueMultiplicative); } public final function GetSkillPathType(skill : ESkill) : ESkillPath { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillPathType(skill); return ESP_NotSet; } public function GetSkillLevel(s : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillLevel(s); return -1; } public function GetSkillMaxLevel(s : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillMaxLevel(s); return -1; } public function GetBoughtSkillLevel(s : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetBoughtSkillLevel(s); return -1; } public function GetAxiiLevel() : int { var level : int; level = 1; if(CanUseSkill(S_Magic_s17)) level += GetSkillLevel(S_Magic_s17); return Clamp(level, 1, 4); } public function IsInFrenzy() : bool { return isInFrenzy; } public function HasRecentlyCountered() : bool { return hasRecentlyCountered; } public function SetRecentlyCountered(counter : bool) { hasRecentlyCountered = counter; } timer function CheckBlockedSkills(dt : float, id : int) { var nextCallTime : float; nextCallTime = ((W3PlayerAbilityManager)abilityManager).CheckBlockedSkills(dt); if(nextCallTime != -1) AddTimer('CheckBlockedSkills', nextCallTime, , , , true); } public function RemoveTemporarySkills() { var i : int; var pam : W3PlayerAbilityManager; if(tempLearnedSignSkills.Size() > 0) { pam = (W3PlayerAbilityManager)abilityManager; for(i=0; i { pam.RemoveTemporarySkill(tempLearnedSignSkills[i]); } tempLearnedSignSkills.Clear(); } RemoveAbilityAll(SkillEnumToName(S_Sword_s19)); } public function RemoveTemporarySkill(skill : SSimpleSkill) : bool { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; if(pam && pam.IsInitialized()) return pam.RemoveTemporarySkill(skill); return false; } private function AddTemporarySkills() { if(CanUseSkill(S_Sword_s19) && GetStat(BCS_Focus) >= 3) { tempLearnedSignSkills = ((W3PlayerAbilityManager)abilityManager).AddTempNonAlchemySkills(); DrainFocus(GetStat(BCS_Focus)); AddAbilityMultiple(SkillEnumToName(S_Sword_s19), GetSkillLevel(S_Sword_s19)); } } public function HasAlternateQuen() : bool { var quenEntity : W3QuenEntity; quenEntity = (W3QuenEntity)GetCurrentSignEntity(); if(quenEntity) { return quenEntity.IsAlternateCast(); } return false; } public function AddPoints(type : ESpendablePointType, amount : int, show : bool) { levelManager.AddPoints(type, amount, show); } public function GetLevel() : int {return levelManager.GetLevel();} public function GetMaxLevel() : int {return levelManager.GetMaxLevel();} public function GetTotalExpForNextLevel() : int {return levelManager.GetTotalExpForNextLevel();} public function GetPointsTotal(type : ESpendablePointType) : int {return levelManager.GetPointsTotal(type);} public function IsAutoLeveling() : bool {return autoLevel;} public function SetAutoLeveling( b : bool ) {autoLevel = b;} public function GetMissingExpForNextLevel() : int { return Max(0, GetTotalExpForNextLevel() - GetPointsTotal(EExperiencePoint)); } private saved var runewordInfusionType : ESignType; default runewordInfusionType = ST_None; public final function GetRunewordInfusionType() : ESignType { return runewordInfusionType; } public function QuenImpulse( isAlternate : bool, signEntity : W3QuenEntity, source : string, optional forceSkillLevel : int ) { var level, i, j : int; var atts, damages : array; var ents : array; var action : W3DamageAction; var dm : CDefinitionsManagerAccessor; var skillAbilityName : name; var dmg : float; var min, max : SAbilityAttributeValue; var pos : Vector; if( forceSkillLevel > 0 ) { level = forceSkillLevel; } else { level = GetSkillLevel(S_Magic_s13); } dm = theGame.GetDefinitionsManager(); skillAbilityName = GetSkillAbilityName(S_Magic_s13); if(level >= 2) { dm.GetAbilityAttributes(skillAbilityName, atts); for(i=0; i { if(IsDamageTypeNameValid(atts[i])) { damages.PushBack(atts[i]); } } } pos = signEntity.GetWorldPosition(); FindGameplayEntitiesInSphere(ents, pos, 3, 1000, '', FLAG_OnlyAliveActors + FLAG_ExcludeTarget + FLAG_Attitude_Hostile + FLAG_Attitude_Neutral + FLAG_TestLineOfSight, this); for(i=0; i { action = new W3DamageAction in theGame; action.Initialize(this, ents[i], signEntity, source, EHRT_Heavy, CPS_SpellPower, false, false, true, false); action.SetSignSkill(S_Magic_s13); action.SetCannotReturnDamage(true); action.SetProcessBuffsIfNoDamage(true); if(!isAlternate && level >= 2) { action.SetHitEffect('hit_electric_quen'); action.SetHitEffect('hit_electric_quen', true); action.SetHitEffect('hit_electric_quen', false, true); action.SetHitEffect('hit_electric_quen', true, true); } if(level >= 1) { action.AddEffectInfo(EET_Stagger); } if(level >= 2) { for(j=0; j { dm.GetAbilityAttributeValue(skillAbilityName, damages[j], min, max); dmg = CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); if( IsSetBonusActive( EISB_Bear_2 ) ) { dm.GetAbilityAttributeValue( GetSetBonusAbility( EISB_Bear_2 ), 'quen_dmg_boost', min, max ); dmg *= 1 + min.valueMultiplicative; } action.AddDamage(damages[j], dmg); } } if(level == 3) { action.AddEffectInfo(EET_KnockdownTypeApplicator); } theGame.damageMgr.ProcessAction( action ); delete action; } if(isAlternate) { signEntity.PlayHitEffect('quen_impulse_explode', signEntity.GetWorldRotation()); signEntity.EraseFirstTimeStamp(); if(level >= 2) { if( !IsSetBonusActive( EISB_Bear_2 ) ) { signEntity.PlayHitEffect('quen_electric_explode', signEntity.GetWorldRotation()); } else { signEntity.PlayHitEffect('quen_electric_explode_bear_abl2', signEntity.GetWorldRotation()); } } } else { signEntity.PlayEffect('lasting_shield_impulse'); } } public function OnSignCastPerformed(signType : ESignType, isAlternate : bool) { var items : array; var weaponEnt : CEntity; var fxName : name; var pos : Vector; super.OnSignCastPerformed(signType, isAlternate); if(HasAbility('Runeword 1 _Stats', true) && GetStat(BCS_Focus) >= 1.0f) { DrainFocus(1.0f); runewordInfusionType = signType; items = inv.GetHeldWeapons(); weaponEnt = inv.GetItemEntityUnsafe(items[0]); weaponEnt.StopEffect('runeword_aard'); weaponEnt.StopEffect('runeword_axii'); weaponEnt.StopEffect('runeword_igni'); weaponEnt.StopEffect('runeword_quen'); weaponEnt.StopEffect('runeword_yrden'); if(signType == ST_Aard) fxName = 'runeword_aard'; else if(signType == ST_Axii) fxName = 'runeword_axii'; else if(signType == ST_Igni) fxName = 'runeword_igni'; else if(signType == ST_Quen) fxName = 'runeword_quen'; else if(signType == ST_Yrden) fxName = 'runeword_yrden'; weaponEnt.PlayEffect(fxName); } if( IsMutationActive( EPMT_Mutation6 ) && signType == ST_Aard && !isAlternate ) { pos = GetWorldPosition() + GetWorldForward() * 2; theGame.GetSurfacePostFX().AddSurfacePostFXGroup( pos, 0.f, 3.f, 2.f, 5.f, 0 ); } } public saved var savedQuenHealth, savedQuenDuration : float; timer function HACK_QuenSaveStatus(dt : float, id : int) { var quenEntity : W3QuenEntity; quenEntity = (W3QuenEntity)signs[ST_Quen].entity; savedQuenHealth = quenEntity.GetShieldHealth(); savedQuenDuration = quenEntity.GetShieldRemainingDuration(); } timer function DelayedRestoreQuen(dt : float, id : int) { RestoreQuen(savedQuenHealth, savedQuenDuration); } public final function OnBasicQuenFinishing() { RemoveTimer('HACK_QuenSaveStatus'); savedQuenHealth = 0.f; savedQuenDuration = 0.f; } public final function IsAnyQuenActive() : bool { var quen : W3QuenEntity; quen = (W3QuenEntity)GetSignEntity(ST_Quen); if(quen) return quen.IsAnyQuenActive(); return false; } public final function IsQuenActive(alternateMode : bool) : bool { if(IsAnyQuenActive() && GetSignEntity(ST_Quen).IsAlternateCast() == alternateMode) return true; return false; } public function FinishQuen( skipVisuals : bool, optional forceNoBearSetBonus : bool ) { var quen : W3QuenEntity; quen = (W3QuenEntity)GetSignEntity(ST_Quen); if(quen) quen.ForceFinishQuen( skipVisuals, forceNoBearSetBonus ); } public function GetTotalSignSpellPower(signSkill : ESkill) : SAbilityAttributeValue { var sp : SAbilityAttributeValue; var penalty : SAbilityAttributeValue; var penaltyReduction : float; var penaltyReductionLevel : int; sp = GetSkillAttributeValue(signSkill, PowerStatEnumToName(CPS_SpellPower), true, true); if ( signSkill == S_Magic_s01 ) { penaltyReductionLevel = GetSkillLevel(S_Magic_s01) + 1; if(penaltyReductionLevel > 0) { penaltyReduction = 1 - penaltyReductionLevel * CalculateAttributeValue(GetSkillAttributeValue(S_Magic_s01, 'spell_power_penalty_reduction', true, true)); penalty = GetSkillAttributeValue(S_Magic_s01, PowerStatEnumToName(CPS_SpellPower), false, false); sp += penalty * penaltyReduction; } } if(signSkill == S_Magic_1 || signSkill == S_Magic_s01) { sp += GetAttributeValue('spell_power_aard'); } else if(signSkill == S_Magic_2 || signSkill == S_Magic_s02) { sp += GetAttributeValue('spell_power_igni'); } else if(signSkill == S_Magic_3 || signSkill == S_Magic_s03) { sp += GetAttributeValue('spell_power_yrden'); } else if(signSkill == S_Magic_4 || signSkill == S_Magic_s04) { sp += GetAttributeValue('spell_power_quen'); } else if(signSkill == S_Magic_5 || signSkill == S_Magic_s05) { sp += GetAttributeValue('spell_power_axii'); } ApplyMutation10StatBoost( sp ); return sp; } public final function GetGwentCardIndex( cardName : name ) : int { var dm : CDefinitionsManagerAccessor; dm = theGame.GetDefinitionsManager(); if(dm.ItemHasTag( cardName , 'GwintCardLeader' )) { return theGame.GetGwintManager().GwentLeadersNametoInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardNrkd' )) { return theGame.GetGwintManager().GwentNrkdNameToInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardNlfg' )) { return theGame.GetGwintManager().GwentNlfgNameToInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardSctl' )) { return theGame.GetGwintManager().GwentSctlNameToInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardMstr' )) { return theGame.GetGwintManager().GwentMstrNameToInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardSke' )) { return theGame.GetGwintManager().GwentSkeNameToInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardNeutral' )) { return theGame.GetGwintManager().GwentNeutralNameToInt( cardName ); } else if(dm.ItemHasTag( cardName , 'GwintCardSpcl' )) { return theGame.GetGwintManager().GwentSpecialNameToInt( cardName ); } return -1; } public final function AddGwentCard(cardName : name, amount : int) : bool { var dm : CDefinitionsManagerAccessor; var cardIndex, i : int; var tut : STutorialMessage; var gwintManager : CR4GwintManager; if(FactsQuerySum("q001_nightmare_ended") > 0 && ShouldProcessTutorial('TutorialGwentDeckBuilder2')) { tut.type = ETMT_Hint; tut.tutorialScriptTag = 'TutorialGwentDeckBuilder2'; tut.journalEntryName = 'TutorialGwentDeckBuilder2'; tut.hintPositionType = ETHPT_DefaultGlobal; tut.markAsSeenOnShow = true; tut.hintDurationType = ETHDT_Long; theGame.GetTutorialSystem().DisplayTutorial(tut); } dm = theGame.GetDefinitionsManager(); cardIndex = GetGwentCardIndex(cardName); if (cardIndex != -1) { FactsAdd("Gwint_Card_Looted"); for(i = 0; i < amount; i += 1) { theGame.GetGwintManager().AddCardToCollection( cardIndex ); } } if( dm.ItemHasTag( cardName, 'GwentTournament' ) ) { if ( dm.ItemHasTag( cardName, 'GT1' ) ) { FactsAdd( "GwentTournament", 1 ); } else if ( dm.ItemHasTag( cardName, 'GT2' ) ) { FactsAdd( "GwentTournament", 2 ); } else if ( dm.ItemHasTag( cardName, 'GT3' ) ) { FactsAdd( "GwentTournament", 3 ); } else if ( dm.ItemHasTag( cardName, 'GT4' ) ) { FactsAdd( "GwentTournament", 4 ); } else if ( dm.ItemHasTag( cardName, 'GT5' ) ) { FactsAdd( "GwentTournament", 5 ); } else if ( dm.ItemHasTag( cardName, 'GT6' ) ) { FactsAdd( "GwentTournament", 6 ); } else if ( dm.ItemHasTag( cardName, 'GT7' ) ) { FactsAdd( "GwentTournament", 7 ); } CheckGwentTournamentDeck(); } if( dm.ItemHasTag( cardName, 'EP2Tournament' ) ) { if ( dm.ItemHasTag( cardName, 'GT1' ) ) { FactsAdd( "EP2Tournament", 1 ); } else if ( dm.ItemHasTag( cardName, 'GT2' ) ) { FactsAdd( "EP2Tournament", 2 ); } else if ( dm.ItemHasTag( cardName, 'GT3' ) ) { FactsAdd( "EP2Tournament", 3 ); } else if ( dm.ItemHasTag( cardName, 'GT4' ) ) { FactsAdd( "EP2Tournament", 4 ); } else if ( dm.ItemHasTag( cardName, 'GT5' ) ) { FactsAdd( "EP2Tournament", 5 ); } else if ( dm.ItemHasTag( cardName, 'GT6' ) ) { FactsAdd( "EP2Tournament", 6 ); } else if ( dm.ItemHasTag( cardName, 'GT7' ) ) { FactsAdd( "EP2Tournament", 7 ); } CheckEP2TournamentDeck(); } gwintManager = theGame.GetGwintManager(); if( !gwintManager.IsDeckUnlocked( GwintFaction_Skellige ) && gwintManager.HasCardsOfFactionInCollection( GwintFaction_Skellige, false ) ) { gwintManager.UnlockDeck( GwintFaction_Skellige ); } return true; } public final function RemoveGwentCard(cardName : name, amount : int) : bool { var dm : CDefinitionsManagerAccessor; var cardIndex, i : int; dm = theGame.GetDefinitionsManager(); if(dm.ItemHasTag( cardName , 'GwintCardLeader' )) { cardIndex = theGame.GetGwintManager().GwentLeadersNametoInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardNrkd' )) { cardIndex = theGame.GetGwintManager().GwentNrkdNameToInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardNlfg' )) { cardIndex = theGame.GetGwintManager().GwentNlfgNameToInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardSctl' )) { cardIndex = theGame.GetGwintManager().GwentSctlNameToInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardMstr' )) { cardIndex = theGame.GetGwintManager().GwentMstrNameToInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardNeutral' )) { cardIndex = theGame.GetGwintManager().GwentNeutralNameToInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardSpcl' )) { cardIndex = theGame.GetGwintManager().GwentSpecialNameToInt( cardName ); for(i=0; i theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } if( dm.ItemHasTag( cardName, 'GwentTournament' ) ) { if ( dm.ItemHasTag( cardName, 'GT1' ) ) { FactsSubstract( "GwentTournament", 1 ); } else if ( dm.ItemHasTag( cardName, 'GT2' ) ) { FactsSubstract( "GwentTournament", 2 ); } else if ( dm.ItemHasTag( cardName, 'GT3' ) ) { FactsSubstract( "GwentTournament", 3 ); } else if ( dm.ItemHasTag( cardName, 'GT4' ) ) { FactsSubstract( "GwentTournament", 4 ); } else if ( dm.ItemHasTag( cardName, 'GT5' ) ) { FactsSubstract( "GwentTournament", 5 ); } else if ( dm.ItemHasTag( cardName, 'GT6' ) ) { FactsSubstract( "GwentTournament", 6 ); } else if ( dm.ItemHasTag( cardName, 'GT7' ) ) { FactsSubstract( "GwentTournament", 7 ); } CheckGwentTournamentDeck(); } if( dm.ItemHasTag( cardName, 'EP2Tournament' ) ) { if ( dm.ItemHasTag( cardName, 'GT1' ) ) { FactsSubstract( "EP2Tournament", 1 ); } else if ( dm.ItemHasTag( cardName, 'GT2' ) ) { FactsSubstract( "EP2Tournament", 2 ); } else if ( dm.ItemHasTag( cardName, 'GT3' ) ) { FactsSubstract( "EP2Tournament", 3 ); } else if ( dm.ItemHasTag( cardName, 'GT4' ) ) { FactsSubstract( "EP2Tournament", 4 ); } else if ( dm.ItemHasTag( cardName, 'GT5' ) ) { FactsSubstract( "EP2Tournament", 5 ); } else if ( dm.ItemHasTag( cardName, 'GT6' ) ) { FactsSubstract( "EP2Tournament", 6 ); } else if ( dm.ItemHasTag( cardName, 'GT7' ) ) { FactsSubstract( "EP2Tournament", 7 ); } CheckEP2TournamentDeck(); } return true; } function CheckGwentTournamentDeck() { var gwentPower : int; var neededGwentPower : int; var checkBreakpoint : int; neededGwentPower = 70; checkBreakpoint = neededGwentPower/5; gwentPower = FactsQuerySum( "GwentTournament" ); if ( gwentPower >= neededGwentPower ) { FactsAdd( "HasGwentTournamentDeck", 1 ); } else { if( FactsDoesExist( "HasGwentTournamentDeck" ) ) { FactsRemove( "HasGwentTournamentDeck" ); } if ( gwentPower >= checkBreakpoint ) { FactsAdd( "GwentTournamentObjective1", 1 ); } else if ( FactsDoesExist( "GwentTournamentObjective1" ) ) { FactsRemove( "GwentTournamentObjective1" ); } if ( gwentPower >= checkBreakpoint*2 ) { FactsAdd( "GwentTournamentObjective2", 1 ); } else if ( FactsDoesExist( "GwentTournamentObjective2" ) ) { FactsRemove( "GwentTournamentObjective2" ); } if ( gwentPower >= checkBreakpoint*3 ) { FactsAdd( "GwentTournamentObjective3", 1 ); } else if ( FactsDoesExist( "GwentTournamentObjective3" ) ) { FactsRemove( "GwentTournamentObjective3" ); } if ( gwentPower >= checkBreakpoint*4 ) { FactsAdd( "GwentTournamentObjective4", 1 ); } else if ( FactsDoesExist( "GwentTournamentObjective4" ) ) { FactsRemove( "GwentTournamentObjective4" ); } } } function CheckEP2TournamentDeck() { var gwentPower : int; var neededGwentPower : int; var checkBreakpoint : int; neededGwentPower = 24; checkBreakpoint = neededGwentPower/5; gwentPower = FactsQuerySum( "EP2Tournament" ); if ( gwentPower >= neededGwentPower ) { if( FactsQuerySum( "HasEP2TournamentDeck") == 0 ) { FactsAdd( "HasEP2TournamentDeck", 1 ); } } else { if( FactsDoesExist( "HasEP2TournamentDeck" ) ) { FactsRemove( "HasEP2TournamentDeck" ); } if ( gwentPower >= checkBreakpoint ) { FactsAdd( "EP2TournamentObjective1", 1 ); } else if ( FactsDoesExist( "EP2TournamentObjective1" ) ) { FactsRemove( "EP2TournamentObjective1" ); } if ( gwentPower >= checkBreakpoint*2 ) { FactsAdd( "EP2TournamentObjective2", 1 ); } else if ( FactsDoesExist( "EP2TournamentObjective2" ) ) { FactsRemove( "EP2TournamentObjective2" ); } if ( gwentPower >= checkBreakpoint*3 ) { FactsAdd( "EP2TournamentObjective3", 1 ); } else if ( FactsDoesExist( "EP2TournamentObjective3" ) ) { FactsRemove( "EP2TournamentObjective3" ); } if ( gwentPower >= checkBreakpoint*4 ) { FactsAdd( "EP2TournamentObjective4", 1 ); } else if ( FactsDoesExist( "EP2TournamentObjective4" ) ) { FactsRemove( "EP2TournamentObjective4" ); } } } public function SimulateBuffTimePassing(simulatedTime : float) { super.SimulateBuffTimePassing(simulatedTime); FinishQuen(true); } public function CanMeditate() : bool { var currentStateName : name; currentStateName = GetCurrentStateName(); if(currentStateName == 'Exploration' && !CanPerformPlayerAction()) return false; if(GetCurrentStateName() != 'Exploration' && GetCurrentStateName() != 'Meditation' && GetCurrentStateName() != 'MeditationWaiting') return false; if(GetUsedVehicle()) return false; return CanMeditateHere(); } public final function CanMeditateWait(optional skipMeditationStateCheck : bool) : bool { var currState : name; currState = GetCurrentStateName(); if(!skipMeditationStateCheck && currState != 'Meditation') return false; if(theGame.IsGameTimePaused()) return false; if(!IsActionAllowed( EIAB_MeditationWaiting )) return false; return true; } public final function CanMeditateHere() : bool { var pos : Vector; pos = GetWorldPosition(); if(pos.Z <= theGame.GetWorld().GetWaterLevel(pos, true) && IsInShallowWater()) return false; if(IsThreatened()) return false; return true; } public function Meditate() : bool { var medState : W3PlayerWitcherStateMeditation; var stateName : name; stateName = GetCurrentStateName(); if (!CanMeditate() || stateName == 'MeditationWaiting' ) return false; GotoState('Meditation'); medState = (W3PlayerWitcherStateMeditation)GetState('Meditation'); medState.SetMeditationPointHeading(GetHeading()); return true; } public final function MeditationRestoring(simulatedTime : float) { if ( theGame.GetDifficultyMode() != EDM_Hard && theGame.GetDifficultyMode() != EDM_Hardcore ) { Heal(GetStatMax(BCS_Vitality)); } abilityManager.DrainToxicity( abilityManager.GetStat( BCS_Toxicity ) ); abilityManager.DrainFocus( abilityManager.GetStat( BCS_Focus ) ); inv.SingletonItemsRefillAmmo(); SimulateBuffTimePassing(simulatedTime); ApplyWitcherHouseBuffs(); } var clockMenu : CR4MeditationClockMenu; public function MeditationClockStart(m : CR4MeditationClockMenu) { clockMenu = m; AddTimer('UpdateClockTime',0.1,true); } public function MeditationClockStop() { clockMenu = NULL; RemoveTimer('UpdateClockTime'); } public timer function UpdateClockTime(dt : float, id : int) { if(clockMenu) clockMenu.UpdateCurrentHours(); else RemoveTimer('UpdateClockTime'); } private var waitTimeHour : int; public function SetWaitTargetHour(t : int) { waitTimeHour = t; } public function GetWaitTargetHour() : int { return waitTimeHour; } public function MeditationForceAbort(forceCloseUI : bool) { var waitt : W3PlayerWitcherStateMeditationWaiting; var medd : W3PlayerWitcherStateMeditation; var currentStateName : name; currentStateName = GetCurrentStateName(); if(currentStateName == 'MeditationWaiting') { waitt = (W3PlayerWitcherStateMeditationWaiting)GetCurrentState(); if(waitt) { waitt.StopRequested(forceCloseUI); } } else if(currentStateName == 'Meditation') { medd = (W3PlayerWitcherStateMeditation)GetCurrentState(); if(medd) { medd.StopRequested(forceCloseUI); } } if(forceCloseUI && theGame.GetGuiManager().IsAnyMenu()) { theGame.GetGuiManager().GetRootMenu().CloseMenu(); DisplayActionDisallowedHudMessage(EIAB_MeditationWaiting, false, false, true, false); } } public function Runeword10Triggerred() { var min, max : SAbilityAttributeValue; theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Runeword 10 _Stats', 'stamina', min, max ); GainStat(BCS_Stamina, min.valueMultiplicative * GetStatMax(BCS_Stamina)); PlayEffect('runeword_10_stamina'); } public function Runeword12Triggerred() { var min, max : SAbilityAttributeValue; theGame.GetDefinitionsManager().GetAbilityAttributeValue( 'Runeword 12 _Stats', 'focus', min, max ); GainStat(BCS_Focus, RandRangeF(max.valueAdditive, min.valueAdditive)); PlayEffect('runeword_20_adrenaline'); } var runeword10TriggerredOnFinisher, runeword12TriggerredOnFinisher : bool; event OnFinisherStart() { super.OnFinisherStart(); runeword10TriggerredOnFinisher = false; runeword12TriggerredOnFinisher = false; } public function ApplyWitcherHouseBuffs() { var l_bed : W3WitcherBed; if( FactsQuerySum( "PlayerInsideInnerWitcherHouse" ) > 0 ) { l_bed = (W3WitcherBed)theGame.GetEntityByTag( 'witcherBed' ); if( l_bed.GetWasUsed() ) { if( l_bed.GetBedLevel() != 0 ) { AddEffectDefault( EET_WellRested, this, "Bed Buff" ); } if( FactsQuerySum( "StablesExists" ) ) { AddEffectDefault( EET_HorseStableBuff, this, "Stables" ); } if( l_bed.GetWereItemsRefilled() ) { theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt( "message_common_alchemy_table_buff_applied" ),, true ); l_bed.SetWereItemsRefilled( false ); } AddEffectDefault( EET_BookshelfBuff, this, "Bookshelf" ); Heal( GetStatMax( BCS_Vitality ) ); } } } public function CheatResurrect() { super.CheatResurrect(); theGame.ReleaseNoSaveLock(theGame.deathSaveLockId); theInput.RestoreContext( 'Exploration', true ); } public function Debug_EquipTestingSkills(equip : bool, force : bool) { var skills : array; var i, slot : int; ((W3PlayerAbilityManager)abilityManager).OnLevelGained(36); skills.PushBack(S_Magic_s01); skills.PushBack(S_Magic_s02); skills.PushBack(S_Magic_s03); skills.PushBack(S_Magic_s04); skills.PushBack(S_Magic_s05); skills.PushBack(S_Sword_s01); skills.PushBack(S_Sword_s02); if(equip) { for(i=0; i { if(!force && IsSkillEquipped(skills[i])) continue; if(GetSkillLevel(skills[i]) == 0) AddSkill(skills[i]); if(force) slot = i+1; else slot = GetFreeSkillSlot(); EquipSkill(skills[i], slot); } } else { for(i=0; i { UnequipSkill(GetSkillSlotID(skills[i])); } } } public function Debug_ClearCharacterDevelopment(optional keepInv : bool) { var template : CEntityTemplate; var entity : CEntity; var invTesting : CInventoryComponent; var i : int; var items : array; var abs : array; delete abilityManager; delete levelManager; delete effectManager; GetCharacterStats().GetAbilities(abs, false); for(i=0; i RemoveAbility(abs[i]); abs.Clear(); GetCharacterStatsParam(abs); for(i=0; i AddAbility(abs[i]); levelManager = new W3LevelManager in this; levelManager.Initialize(); levelManager.PostInit(this, false, true); AddAbility('GeraltSkills_Testing'); SetAbilityManager(); abilityManager.Init(this, GetCharacterStats(), false, theGame.GetDifficultyMode()); SetEffectManager(); abilityManager.PostInit(); if(!keepInv) { inv.RemoveAllItems(); } template = (CEntityTemplate)LoadResource("geralt_inventory_release"); entity = theGame.CreateEntity(template, Vector(0,0,0)); invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent'); invTesting.GiveAllItemsTo(inv, true); entity.Destroy(); inv.GetAllItems(items); for(i=0; i { if(!inv.ItemHasTag(items[i], 'NoDrop')) EquipItem(items[i]); } Debug_GiveTestingItems(0); } function Debug_BearSetBonusQuenSkills() { var skills : array; var i, slot : int; skills.PushBack(S_Magic_s04); skills.PushBack(S_Magic_s14); for(i=0; i { if(GetSkillLevel(skills[i]) == 0) { AddSkill(skills[i]); } slot = GetFreeSkillSlot(); EquipSkill(skills[i], slot); } } final function Debug_HAX_UnlockSkillSlot(slotIndex : int) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).Debug_HAX_UnlockSkillSlot(slotIndex); return false; } public function GetLevelupAbility( id : int) : name { switch(id) { case 1: return 'Lvl1'; case 2: return 'Lvl2'; case 3: return 'Lvl3'; case 4: return 'Lvl4'; case 5: return 'Lvl5'; case 6: return 'Lvl6'; case 7: return 'Lvl7'; case 8: return 'Lvl8'; case 9: return 'Lvl9'; case 10: return 'Lvl10'; case 11: return 'Lvl11'; case 12: return 'Lvl12'; case 13: return 'Lvl13'; case 14: return 'Lvl14'; case 15: return 'Lvl15'; case 16: return 'Lvl16'; case 17: return 'Lvl17'; case 18: return 'Lvl18'; case 19: return 'Lvl19'; case 20: return 'Lvl20'; case 21: return 'Lvl21'; case 22: return 'Lvl22'; case 23: return 'Lvl23'; case 24: return 'Lvl24'; case 25: return 'Lvl25'; case 26: return 'Lvl26'; case 27: return 'Lvl27'; case 28: return 'Lvl28'; case 29: return 'Lvl29'; case 30: return 'Lvl30'; case 31: return 'Lvl31'; case 32: return 'Lvl32'; case 33: return 'Lvl33'; case 34: return 'Lvl34'; case 35: return 'Lvl35'; case 36: return 'Lvl36'; case 37: return 'Lvl37'; case 38: return 'Lvl38'; case 39: return 'Lvl39'; case 40: return 'Lvl40'; case 41: return 'Lvl41'; case 42: return 'Lvl42'; case 43: return 'Lvl43'; case 44: return 'Lvl44'; case 45: return 'Lvl45'; case 46: return 'Lvl46'; case 47: return 'Lvl47'; case 48: return 'Lvl48'; case 49: return 'Lvl49'; case 50: return 'Lvl50'; default: return ''; } return ''; } public function CanSprint( speed : float ) : bool { if( !super.CanSprint( speed ) ) { return false; } if( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) { if ( this.GetPlayerCombatStance() == PCS_AlertNear ) { if ( IsSprintActionPressed() ) OnRangedForceHolster( true, false ); } else return false; } if( GetCurrentStateName() != 'Swimming' && GetStat(BCS_Stamina) <= 0 ) { SetSprintActionPressed(false,true); return false; } return true; } public function ManageSleeping() { thePlayer.RemoveBuffImmunity_AllCritical( 'Bed' ); thePlayer.RemoveBuffImmunity_AllNegative( 'Bed' ); thePlayer.PlayerStopAction( PEA_GoToSleep ); } public function RestoreHorseManager() : bool { var horseTemplate : CEntityTemplate; var horseManager : W3HorseManager; if ( GetHorseManager() ) { return false; } horseTemplate = (CEntityTemplate)LoadResource("horse_manager"); horseManager = (W3HorseManager)theGame.CreateEntity(horseTemplate, GetWorldPosition(),,,,,PM_Persist); horseManager.CreateAttachment(this); horseManager.OnCreated(); EntityHandleSet( horseManagerHandle, horseManager ); return true; } final function PerformParryCheck( parryInfo : SParryInfo ) : bool { if( super.PerformParryCheck( parryInfo ) ) { GainAdrenalineFromPerk21( 'parry' ); return true; } return false; } protected final function PerformCounterCheck( parryInfo: SParryInfo ) : bool { var fistFightCheck, isInFistFight : bool; if( super.PerformCounterCheck( parryInfo ) ) { GainAdrenalineFromPerk21( 'counter' ); isInFistFight = FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightCheck ); if( isInFistFight && fistFightCheck ) { FactsAdd( "statistics_fist_fight_counter" ); AddTimer( 'FistFightCounterTimer', 0.5f, , , , true ); } return true; } return false; } public function GainAdrenalineFromPerk21( n : name ) { var perkStats, perkTime : SAbilityAttributeValue; var targets : array; targets = GetHostileEnemies(); if( !CanUseSkill( S_Perk_21 ) || targets.Size() == 0 ) { return; } perkTime = GetSkillAttributeValue( S_Perk_21, 'perk21Time', false, false ); if( theGame.GetEngineTimeAsSeconds() >= timeForPerk21 + perkTime.valueAdditive ) { perkStats = GetSkillAttributeValue( S_Perk_21, n , false, false ); GainStat( BCS_Focus, perkStats.valueAdditive ); timeForPerk21 = theGame.GetEngineTimeAsSeconds(); AddEffectDefault( EET_Perk21InternalCooldown, this, "Perk21", false ); } } timer function FistFightCounterTimer( dt : float, id : int ) { FactsRemove( "statistics_fist_fight_counter" ); } public final function IsSignBlocked(signType : ESignType) : bool { switch( signType ) { case ST_Aard : return IsRadialSlotBlocked ( 'Aard'); break; case ST_Axii : return IsRadialSlotBlocked ( 'Axii'); break; case ST_Igni : return IsRadialSlotBlocked ( 'Igni'); break; case ST_Quen : return IsRadialSlotBlocked ( 'Quen'); break; case ST_Yrden : return IsRadialSlotBlocked ( 'Yrden'); break; default: break; } return false; } public final function AddAnItemWithAutogenLevelAndQuality(itemName : name, desiredLevel : int, minQuality : int, optional equipItem : bool) { var itemLevel, quality : int; var ids : array; var attemptCounter : int; itemLevel = 0; quality = 0; attemptCounter = 0; while(itemLevel != desiredLevel || quality < minQuality) { attemptCounter += 1; ids.Clear(); ids = inv.AddAnItem(itemName, 1, true); itemLevel = inv.GetItemLevel(ids[0]); quality = RoundMath(CalculateAttributeValue(inv.GetItemAttributeValue(ids[0], 'quality'))); if(attemptCounter >= 1000) break; if(itemLevel != desiredLevel || quality < minQuality) inv.RemoveItem(ids[0]); } if(equipItem) EquipItem(ids[0]); } public final function AddAnItemWithAutogenLevel(itemName : name, desiredLevel : int) { var itemLevel : int; var ids : array; var attemptCounter : int; itemLevel = 0; while(itemLevel != desiredLevel) { attemptCounter += 1; ids.Clear(); ids = inv.AddAnItem(itemName, 1, true); itemLevel = inv.GetItemLevel(ids[0]); if(attemptCounter >= 1000) break; if(itemLevel != desiredLevel) inv.RemoveItem(ids[0]); } } public final function AddAnItemWithMinQuality(itemName : name, minQuality : int, optional equip : bool) { var quality : int; var ids : array; var attemptCounter : int; quality = 0; while(quality < minQuality) { attemptCounter += 1; ids.Clear(); ids = inv.AddAnItem(itemName, 1, true); quality = RoundMath(CalculateAttributeValue(inv.GetItemAttributeValue(ids[0], 'quality'))); if(attemptCounter >= 1000) break; if(quality < minQuality) inv.RemoveItem(ids[0]); } if(equip) EquipItem(ids[0]); } public function IsSetBonusActive( bonus : EItemSetBonus ) : bool { switch(bonus) { case EISB_Lynx_1: return amountOfSetPiecesEquipped[ EIST_Lynx ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS; case EISB_Lynx_2: return amountOfSetPiecesEquipped[ EIST_Lynx ] >= theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS; case EISB_Gryphon_1: return amountOfSetPiecesEquipped[ EIST_Gryphon ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS; case EISB_Gryphon_2: return amountOfSetPiecesEquipped[ EIST_Gryphon ] >= theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS; case EISB_Bear_1: return amountOfSetPiecesEquipped[ EIST_Bear ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS; case EISB_Bear_2: return amountOfSetPiecesEquipped[ EIST_Bear ] >= theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS; case EISB_Wolf_1: return amountOfSetPiecesEquipped[ EIST_Wolf ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS; case EISB_Wolf_2: return amountOfSetPiecesEquipped[ EIST_Wolf ] >= theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS; case EISB_RedWolf_1: return amountOfSetPiecesEquipped[ EIST_RedWolf ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS; case EISB_RedWolf_2: return amountOfSetPiecesEquipped[ EIST_RedWolf ] >= theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS; case EISB_Vampire: return amountOfSetPiecesEquipped[ EIST_Vampire ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS; default: return false; } } public function GetSetPartsEquipped( setType : EItemSetType ) : int { return amountOfSetPiecesEquipped[ setType ]; } protected function UpdateItemSetBonuses( item : SItemUniqueId, increment : bool ) { var setType : EItemSetType; var tutorialStateSets : W3TutorialManagerUIHandlerStateSetItemsUnlocked; var id : SItemUniqueId; if( !inv.IsIdValid( item ) || !inv.ItemHasTag(item, theGame.params.ITEM_SET_TAG_BONUS ) ) { if( !IsSetBonusActive( EISB_Wolf_1 ) ) { if( GetItemEquippedOnSlot( EES_SteelSword, id ) ) { RemoveExtraOilsFromItem( id ); } if( GetItemEquippedOnSlot( EES_SilverSword, id ) ) { RemoveExtraOilsFromItem( id ); } } return; } setType = CheckSetType( item ); if( increment ) { amountOfSetPiecesEquipped[ setType ] += 1; if( amountOfSetPiecesEquipped[ setType ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS && ShouldProcessTutorial( 'TutorialSetBonusesUnlocked' ) && theGame.GetTutorialSystem().uiHandler && theGame.GetTutorialSystem().uiHandler.GetCurrentStateName() == 'SetItemsUnlocked' ) { tutorialStateSets = ( W3TutorialManagerUIHandlerStateSetItemsUnlocked )theGame.GetTutorialSystem().uiHandler.GetCurrentState(); tutorialStateSets.OnSetBonusCompleted(); } } else { amountOfSetPiecesEquipped[ setType ] -= 1; } if( setType != EIST_Vampire && amountOfSetPiecesEquipped[ setType ] == theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS ) { theGame.GetGamerProfile().AddAchievement( EA_ReadyToRoll ); } if( !IsSetBonusActive( EISB_Wolf_1 ) ) { if( GetItemEquippedOnSlot( EES_SteelSword, id ) ) { RemoveExtraOilsFromItem( id ); } if( GetItemEquippedOnSlot( EES_SilverSword, id ) ) { RemoveExtraOilsFromItem( id ); } } ManageActiveSetBonuses( setType ); ManageSetBonusesSoundbanks( setType ); } public function ManageActiveSetBonuses( setType : EItemSetType ) { var l_i : int; if( setType == EIST_Lynx ) { if( HasBuff( EET_LynxSetBonus ) && !IsSetBonusActive( EISB_Lynx_1 ) ) { RemoveBuff( EET_LynxSetBonus ); } } else if( setType == EIST_Gryphon ) { if( !IsSetBonusActive( EISB_Gryphon_1 ) ) { RemoveBuff( EET_GryphonSetBonus ); } if( IsSetBonusActive( EISB_Gryphon_2 ) && !HasBuff( EET_GryphonSetBonusYrden ) ) { for( l_i = 0 ; l_i < yrdenEntities.Size() ; l_i += 1 ) { if( yrdenEntities[ l_i ].GetIsPlayerInside() && !yrdenEntities[ l_i ].IsAlternateCast() ) { AddEffectDefault( EET_GryphonSetBonusYrden, this, "GryphonSetBonusYrden" ); break; } } } else { RemoveBuff( EET_GryphonSetBonusYrden ); } } } public function CheckSetTypeByName( itemName : name ) : EItemSetType { var dm : CDefinitionsManagerAccessor; dm = theGame.GetDefinitionsManager(); if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_LYNX ) ) { return EIST_Lynx; } else if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_GRYPHON ) ) { return EIST_Gryphon; } else if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_BEAR ) ) { return EIST_Bear; } else if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_WOLF ) ) { return EIST_Wolf; } else if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_RED_WOLF ) ) { return EIST_RedWolf; } else if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_VAMPIRE ) ) { return EIST_Vampire; } else if( dm.ItemHasTag( itemName, theGame.params.ITEM_SET_TAG_VIPER ) ) { return EIST_Viper; } else { return EIST_Undefined; } } public function CheckSetType( item : SItemUniqueId ) : EItemSetType { var stopLoop : bool; var tags : array; var i : int; var setType : EItemSetType; stopLoop = false; inv.GetItemTags( item, tags ); for( i=0; i { switch( tags[i] ) { case theGame.params.ITEM_SET_TAG_LYNX: case theGame.params.ITEM_SET_TAG_GRYPHON: case theGame.params.ITEM_SET_TAG_BEAR: case theGame.params.ITEM_SET_TAG_WOLF: case theGame.params.ITEM_SET_TAG_RED_WOLF: case theGame.params.ITEM_SET_TAG_VAMPIRE: case theGame.params.ITEM_SET_TAG_VIPER: setType = SetItemNameToType( tags[i] ); stopLoop = true; break; } if ( stopLoop ) { break; } } return setType; } public function GetSetBonusStatusByName( itemName : name, out desc1, desc2 : string, out isActive1, isActive2 : bool ) : EItemSetType { var setType : EItemSetType; if( theGame.GetDLCManager().IsEP2Enabled() ) { setType = CheckSetTypeByName( itemName ); SetBonusStatusByType( setType, desc1, desc2, isActive1, isActive2 ); return setType; } else { return EIST_Undefined; } } public function GetSetBonusStatus( item : SItemUniqueId, out desc1, desc2 : string, out isActive1, isActive2 : bool ) : EItemSetType { var setType : EItemSetType; if( theGame.GetDLCManager().IsEP2Enabled() ) { setType = CheckSetType( item ); SetBonusStatusByType( setType, desc1, desc2, isActive1, isActive2 ); return setType; } else { return EIST_Undefined; } } private function SetBonusStatusByType(setType : EItemSetType, out desc1, desc2 : string, out isActive1, isActive2 : bool):void { var setBonus : EItemSetBonus; if( amountOfSetPiecesEquipped[ setType ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS ) { isActive1 = true; } if( amountOfSetPiecesEquipped[ setType ] >= theGame.params.ITEMS_REQUIRED_FOR_MAJOR_SET_BONUS ) { isActive2 = true; } setBonus = ItemSetTypeToItemSetBonus( setType, 1 ); desc1 = GetSetBonusTooltipDescription( setBonus ); setBonus = ItemSetTypeToItemSetBonus( setType, 2 ); desc2 = GetSetBonusTooltipDescription( setBonus ); } public function ItemSetTypeToItemSetBonus( setType : EItemSetType, nr : int ) : EItemSetBonus { var setBonus : EItemSetBonus; if( nr == 1 ) { switch( setType ) { case EIST_Lynx: setBonus = EISB_Lynx_1; break; case EIST_Gryphon: setBonus = EISB_Gryphon_1; break; case EIST_Bear: setBonus = EISB_Bear_1; break; case EIST_Wolf: setBonus = EISB_Wolf_1; break; case EIST_RedWolf: setBonus = EISB_RedWolf_1; break; case EIST_Vampire: setBonus = EISB_Vampire; break; } } else { switch( setType ) { case EIST_Lynx: setBonus = EISB_Lynx_2; break; case EIST_Gryphon: setBonus = EISB_Gryphon_2; break; case EIST_Bear: setBonus = EISB_Bear_2; break; case EIST_Wolf: setBonus = EISB_Wolf_2; break; case EIST_RedWolf: setBonus = EISB_RedWolf_2; break; case EIST_Vampire: setBonus = EISB_Undefined; break; } } return setBonus; } public function GetSetBonusTooltipDescription( bonus : EItemSetBonus ) : string { var finalString : string; var arrString : array; var dm : CDefinitionsManagerAccessor; var min, max : SAbilityAttributeValue; var tempString : string; switch( bonus ) { case EISB_Lynx_1: tempString = "skill_desc_lynx_set_ability1"; break; case EISB_Lynx_2: tempString = "skill_desc_lynx_set_ability2"; break; case EISB_Gryphon_1: tempString = "skill_desc_gryphon_set_ability1"; break; case EISB_Gryphon_2: tempString = "skill_desc_gryphon_set_ability2"; break; case EISB_Bear_1: tempString = "skill_desc_bear_set_ability1"; break; case EISB_Bear_2: tempString = "skill_desc_bear_set_ability2"; break; case EISB_Wolf_1: tempString = "skill_desc_wolf_set_ability2"; break; case EISB_Wolf_2: tempString = "skill_desc_wolf_set_ability1"; break; case EISB_RedWolf_1: tempString = "skill_desc_red_wolf_set_ability1"; break; case EISB_RedWolf_2: tempString = "skill_desc_red_wolf_set_ability2"; break; case EISB_Vampire: tempString = "skill_desc_vampire_set_ability1"; break; default: tempString = ""; break; } dm = theGame.GetDefinitionsManager(); switch( bonus ) { case EISB_Lynx_1: dm.GetAbilityAttributeValue( 'LynxSetBonusEffect', 'duration', min, max ); arrString.PushBack( FloatToString( min.valueAdditive ) ); dm.GetAbilityAttributeValue( 'LynxSetBonusEffect', 'lynx_dmg_boost', min, max ); arrString.PushBack( FloatToString( min.valueAdditive * 100 ) ); arrString.PushBack( FloatToString( min.valueAdditive * 100 * amountOfSetPiecesEquipped[ EIST_Lynx ] ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_Lynx_2: dm.GetAbilityAttributeValue( GetSetBonusAbility( EISB_Lynx_2 ), 'lynx_2_dmg_boost', min, max ); arrString.PushBack( FloatToString( min.valueAdditive * 100 ) ); dm.GetAbilityAttributeValue( GetSetBonusAbility( EISB_Lynx_2 ), 'lynx_2_adrenaline_cost', min, max ); arrString.PushBack( FloatToString( min.valueAdditive ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_Gryphon_1: dm.GetAbilityAttributeValue( 'GryphonSetBonusEffect', 'duration', min, max ); arrString.PushBack( FloatToString( min.valueAdditive ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_Gryphon_2: dm.GetAbilityAttributeValue( 'GryphonSetBonusYrdenEffect', 'trigger_scale', min, max ); arrString.PushBack( FloatToString( ( min.valueAdditive - 1 )* 100) ); dm.GetAbilityAttributeValue( 'GryphonSetBonusYrdenEffect', 'staminaRegen', min, max ); arrString.PushBack( FloatToString( min.valueMultiplicative * 100) ); dm.GetAbilityAttributeValue( 'GryphonSetBonusYrdenEffect', 'spell_power', min, max ); arrString.PushBack( FloatToString( min.valueMultiplicative * 100) ); dm.GetAbilityAttributeValue( 'GryphonSetBonusYrdenEffect', 'gryphon_set_bns_dmg_reduction', min, max ); arrString.PushBack( FloatToString( min.valueAdditive * 100) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_Bear_1: dm.GetAbilityAttributeValue( 'setBonusAbilityBear_1', 'quen_reapply_chance', min, max ); arrString.PushBack( FloatToString( min.valueMultiplicative * 100 ) ); arrString.PushBack( FloatToString( min.valueMultiplicative * 100 * amountOfSetPiecesEquipped[ EIST_Bear ] ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_Bear_2: dm.GetAbilityAttributeValue( 'setBonusAbilityBear_2', 'quen_dmg_boost', min, max ); arrString.PushBack( FloatToString( min.valueMultiplicative * 100 ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_RedWolf_2: dm.GetAbilityAttributeValue( 'setBonusAbilityRedWolf_2', 'amount', min, max ); arrString.PushBack( FloatToString( min.valueAdditive ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; case EISB_Vampire: dm.GetAbilityAttributeValue( 'setBonusAbilityVampire', 'life_percent', min, max ); arrString.PushBack( FloatToString( min.valueAdditive ) ); arrString.PushBack( FloatToString( min.valueAdditive * amountOfSetPiecesEquipped[ EIST_Vampire ] ) ); finalString = GetLocStringByKeyExtWithParams( tempString,,,arrString ); break; default: finalString = GetLocStringByKeyExtWithParams( tempString ); } return finalString; } public function ManageSetBonusesSoundbanks( setType : EItemSetType ) { if( amountOfSetPiecesEquipped[ setType ] >= theGame.params.ITEMS_REQUIRED_FOR_MINOR_SET_BONUS ) { switch( setType ) { case EIST_Lynx: LoadSetBonusSoundBank( "ep2_setbonus_lynx.bnk" ); break; case EIST_Gryphon: LoadSetBonusSoundBank( "ep2_setbonus_gryphon.bnk" ); break; case EIST_Bear: LoadSetBonusSoundBank( "ep2_setbonus_bear.bnk" ); break; } } else { switch( setType ) { case EIST_Lynx: UnloadSetBonusSoundBank( "ep2_setbonus_lynx.bnk" ); break; case EIST_Gryphon: UnloadSetBonusSoundBank( "ep2_setbonus_gryphon.bnk" ); break; case EIST_Bear: UnloadSetBonusSoundBank( "ep2_setbonus_bear.bnk" ); break; } } } public function VampiricSetAbilityRegeneration() { var healthMax : float; var healthToReg : float; healthMax = GetStatMax( BCS_Vitality ); healthToReg = ( amountOfSetPiecesEquipped[ EIST_Vampire ] * healthMax ) / 100; PlayEffect('drain_energy_caretaker_shovel'); GainStat( BCS_Vitality, healthToReg ); } private function LoadSetBonusSoundBank( bankName : string ) { if( !theSound.SoundIsBankLoaded( bankName ) ) { theSound.SoundLoadBank( bankName, true ); } } private function UnloadSetBonusSoundBank( bankName : string ) { if( theSound.SoundIsBankLoaded( bankName ) ) { theSound.SoundUnloadBank( bankName ); } } timer function BearSetBonusQuenReapply( dt : float, id : int ) { var newQuen : W3QuenEntity; newQuen = (W3QuenEntity)theGame.CreateEntity( GetSignTemplate( ST_Quen ), GetWorldPosition(), GetWorldRotation() ); newQuen.Init( signOwner, GetSignEntity( ST_Quen ), true ); newQuen.freeFromBearSetBonus = true; newQuen.OnStarted(); newQuen.OnThrowing(); newQuen.OnEnded(); m_quenReappliedCount += 1; RemoveTimer( 'BearSetBonusQuenReapply'); } public final function StandaloneEp1_1() { var i, inc, quantityLow, randLow, quantityMedium, randMedium, quantityHigh, randHigh, startingMoney : int; var pam : W3PlayerAbilityManager; var ids : array; var STARTING_LEVEL : int; FactsAdd("StandAloneEP1", 1); inv.RemoveAllItems(); inv.AddAnItem('Illusion Medallion', 1, true, true, false); inv.AddAnItem('q103_safe_conduct', 1, true, true, false); theGame.GetGamerProfile().ClearAllAchievementsForEP1(); STARTING_LEVEL = 32; inc = STARTING_LEVEL - GetLevel(); for(i=0; i { levelManager.AddPoints(EExperiencePoint, levelManager.GetTotalExpForNextLevel() - levelManager.GetPointsTotal(EExperiencePoint), false); } levelManager.ResetCharacterDev(); pam = (W3PlayerAbilityManager)abilityManager; if(pam) { pam.ResetCharacterDev(); } levelManager.SetFreeSkillPoints(levelManager.GetLevel() - 1 + 11); inv.AddAnItem('Mutagen red', 4); inv.AddAnItem('Mutagen green', 4); inv.AddAnItem('Mutagen blue', 4); inv.AddAnItem('Lesser mutagen red', 2); inv.AddAnItem('Lesser mutagen green', 2); inv.AddAnItem('Lesser mutagen blue', 2); inv.AddAnItem('Greater mutagen green', 1); inv.AddAnItem('Greater mutagen blue', 2); startingMoney = 40000; if(GetMoney() > startingMoney) { RemoveMoney(GetMoney() - startingMoney); } else { AddMoney( 40000 - GetMoney() ); } ids.Clear(); ids = inv.AddAnItem('EP1 Standalone Starting Armor'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('EP1 Standalone Starting Boots'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('EP1 Standalone Starting Gloves'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('EP1 Standalone Starting Pants'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('EP1 Standalone Starting Steel Sword'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('EP1 Standalone Starting Silver Sword'); EquipItem(ids[0]); inv.AddAnItem('Torch', 1, true, true, false); quantityLow = 1; randLow = 3; quantityMedium = 4; randMedium = 4; quantityHigh = 8; randHigh = 6; inv.AddAnItem('Alghoul bone marrow',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Amethyst dust',quantityLow+RandRange(randLow)); inv.AddAnItem('Arachas eyes',quantityLow+RandRange(randLow)); inv.AddAnItem('Arachas venom',quantityLow+RandRange(randLow)); inv.AddAnItem('Basilisk hide',quantityLow+RandRange(randLow)); inv.AddAnItem('Basilisk venom',quantityLow+RandRange(randLow)); inv.AddAnItem('Bear pelt',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Berserker pelt',quantityLow+RandRange(randLow)); inv.AddAnItem('Coal',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Cotton',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Dark iron ingot',quantityLow+RandRange(randLow)); inv.AddAnItem('Dark iron ore',quantityLow+RandRange(randLow)); inv.AddAnItem('Deer hide',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Diamond dust',quantityLow+RandRange(randLow)); inv.AddAnItem('Draconide leather',quantityLow+RandRange(randLow)); inv.AddAnItem('Drowned dead tongue',quantityLow+RandRange(randLow)); inv.AddAnItem('Drowner brain',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Dwimeryte ingot',quantityLow+RandRange(randLow)); inv.AddAnItem('Dwimeryte ore',quantityLow+RandRange(randLow)); inv.AddAnItem('Emerald dust',quantityLow+RandRange(randLow)); inv.AddAnItem('Endriag chitin plates',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Endriag embryo',quantityLow+RandRange(randLow)); inv.AddAnItem('Ghoul blood',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Goat hide',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Hag teeth',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Hardened leather',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Hardened timber',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Harpy feathers',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Horse hide',quantityLow+RandRange(randLow)); inv.AddAnItem('Iron ore',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Leather straps',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Leather',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Linen',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Meteorite ingot',quantityLow+RandRange(randLow)); inv.AddAnItem('Meteorite ore',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Necrophage skin',quantityLow+RandRange(randLow)); inv.AddAnItem('Nekker blood',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Nekker heart',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Oil',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Phosphorescent crystal',quantityLow+RandRange(randLow)); inv.AddAnItem('Pig hide',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Pure silver',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Rabbit pelt',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Rotfiend blood',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Sapphire dust',quantityLow+RandRange(randLow)); inv.AddAnItem('Silk',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Silver ingot',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Silver ore',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Specter dust',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Steel ingot',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Steel plate',quantityHigh+RandRange(randHigh)); inv.AddAnItem('String',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Thread',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Timber',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Twine',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Venom extract',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Water essence',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Wolf liver',quantityHigh+RandRange(randHigh)); inv.AddAnItem('Wolf pelt',quantityMedium+RandRange(randMedium)); inv.AddAnItem('Alcohest', 5); inv.AddAnItem('Dwarven spirit', 5); ids.Clear(); ids = inv.AddAnItem('Crossbow 5'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('Blunt Bolt', 100); EquipItem(ids[0]); inv.AddAnItem('Broadhead Bolt', 100); inv.AddAnItem('Split Bolt', 100); RemoveAllAlchemyRecipes(); RemoveAllCraftingSchematics(); AddAlchemyRecipe('Recipe for Cat 1'); AddAlchemyRecipe('Recipe for Maribor Forest 1'); AddAlchemyRecipe('Recipe for Petris Philtre 1'); AddAlchemyRecipe('Recipe for Swallow 1'); AddAlchemyRecipe('Recipe for Tawny Owl 1'); AddAlchemyRecipe('Recipe for White Gull 1'); AddAlchemyRecipe('Recipe for White Honey 1'); AddAlchemyRecipe('Recipe for White Raffards Decoction 1'); AddAlchemyRecipe('Recipe for Beast Oil 1'); AddAlchemyRecipe('Recipe for Cursed Oil 1'); AddAlchemyRecipe('Recipe for Hanged Man Venom 1'); AddAlchemyRecipe('Recipe for Hybrid Oil 1'); AddAlchemyRecipe('Recipe for Insectoid Oil 1'); AddAlchemyRecipe('Recipe for Magicals Oil 1'); AddAlchemyRecipe('Recipe for Necrophage Oil 1'); AddAlchemyRecipe('Recipe for Specter Oil 1'); AddAlchemyRecipe('Recipe for Vampire Oil 1'); AddAlchemyRecipe('Recipe for Draconide Oil 1'); AddAlchemyRecipe('Recipe for Ogre Oil 1'); AddAlchemyRecipe('Recipe for Relic Oil 1'); AddAlchemyRecipe('Recipe for Beast Oil 2'); AddAlchemyRecipe('Recipe for Cursed Oil 2'); AddAlchemyRecipe('Recipe for Hanged Man Venom 2'); AddAlchemyRecipe('Recipe for Hybrid Oil 2'); AddAlchemyRecipe('Recipe for Insectoid Oil 2'); AddAlchemyRecipe('Recipe for Magicals Oil 2'); AddAlchemyRecipe('Recipe for Necrophage Oil 2'); AddAlchemyRecipe('Recipe for Specter Oil 2'); AddAlchemyRecipe('Recipe for Vampire Oil 2'); AddAlchemyRecipe('Recipe for Draconide Oil 2'); AddAlchemyRecipe('Recipe for Ogre Oil 2'); AddAlchemyRecipe('Recipe for Relic Oil 2'); AddAlchemyRecipe('Recipe for Dancing Star 1'); AddAlchemyRecipe('Recipe for Dwimeritum Bomb 1'); AddAlchemyRecipe('Recipe for Grapeshot 1'); AddAlchemyRecipe('Recipe for Samum 1'); AddAlchemyRecipe('Recipe for White Frost 1'); AddAlchemyRecipe('Recipe for Dwarven spirit 1'); AddAlchemyRecipe('Recipe for Alcohest 1'); AddAlchemyRecipe('Recipe for White Gull 1'); AddStartingSchematics(); ids.Clear(); ids = inv.AddAnItem('Swallow 2'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('Thunderbolt 2'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('Tawny Owl 2'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('Grapeshot 2'); EquipItem(ids[0]); ids.Clear(); ids = inv.AddAnItem('Samum 2'); EquipItem(ids[0]); inv.AddAnItem('Dwimeritum Bomb 1'); inv.AddAnItem('Dragons Dream 1'); inv.AddAnItem('Silver Dust Bomb 1'); inv.AddAnItem('White Frost 2'); inv.AddAnItem('Devils Puffball 2'); inv.AddAnItem('Dancing Star 2'); inv.AddAnItem('Beast Oil 1'); inv.AddAnItem('Cursed Oil 1'); inv.AddAnItem('Hanged Man Venom 2'); inv.AddAnItem('Hybrid Oil 1'); inv.AddAnItem('Insectoid Oil 1'); inv.AddAnItem('Magicals Oil 1'); inv.AddAnItem('Necrophage Oil 2'); inv.AddAnItem('Specter Oil 1'); inv.AddAnItem('Vampire Oil 1'); inv.AddAnItem('Draconide Oil 1'); inv.AddAnItem('Relic Oil 1'); inv.AddAnItem('Black Blood 1'); inv.AddAnItem('Blizzard 1'); inv.AddAnItem('Cat 2'); inv.AddAnItem('Full Moon 1'); inv.AddAnItem('Maribor Forest 1'); inv.AddAnItem('Petris Philtre 1'); inv.AddAnItem('White Gull 1', 3); inv.AddAnItem('White Honey 2'); inv.AddAnItem('White Raffards Decoction 1'); inv.AddAnItem('Mutagen 17'); inv.AddAnItem('Mutagen 19'); inv.AddAnItem('Mutagen 27'); inv.AddAnItem('Mutagen 26'); inv.AddAnItem('weapon_repair_kit_1', 5); inv.AddAnItem('weapon_repair_kit_2', 3); inv.AddAnItem('armor_repair_kit_1', 5); inv.AddAnItem('armor_repair_kit_2', 3); quantityMedium = 2; quantityLow = 1; inv.AddAnItem('Rune stribog lesser', quantityMedium); inv.AddAnItem('Rune stribog', quantityLow); inv.AddAnItem('Rune dazhbog lesser', quantityMedium); inv.AddAnItem('Rune dazhbog', quantityLow); inv.AddAnItem('Rune devana lesser', quantityMedium); inv.AddAnItem('Rune devana', quantityLow); inv.AddAnItem('Rune zoria lesser', quantityMedium); inv.AddAnItem('Rune zoria', quantityLow); inv.AddAnItem('Rune morana lesser', quantityMedium); inv.AddAnItem('Rune morana', quantityLow); inv.AddAnItem('Rune triglav lesser', quantityMedium); inv.AddAnItem('Rune triglav', quantityLow); inv.AddAnItem('Rune svarog lesser', quantityMedium); inv.AddAnItem('Rune svarog', quantityLow); inv.AddAnItem('Rune veles lesser', quantityMedium); inv.AddAnItem('Rune veles', quantityLow); inv.AddAnItem('Rune perun lesser', quantityMedium); inv.AddAnItem('Rune perun', quantityLow); inv.AddAnItem('Rune elemental lesser', quantityMedium); inv.AddAnItem('Rune elemental', quantityLow); inv.AddAnItem('Glyph aard lesser', quantityMedium); inv.AddAnItem('Glyph aard', quantityLow); inv.AddAnItem('Glyph axii lesser', quantityMedium); inv.AddAnItem('Glyph axii', quantityLow); inv.AddAnItem('Glyph igni lesser', quantityMedium); inv.AddAnItem('Glyph igni', quantityLow); inv.AddAnItem('Glyph quen lesser', quantityMedium); inv.AddAnItem('Glyph quen', quantityLow); inv.AddAnItem('Glyph yrden lesser', quantityMedium); inv.AddAnItem('Glyph yrden', quantityLow); StandaloneEp1_2(); } public final function StandaloneEp1_2() { var horseId : SItemUniqueId; var ids : array; var ents : array< CJournalBase >; var i : int; var manager : CWitcherJournalManager; inv.AddAnItem( 'Cows milk', 20 ); ids.Clear(); ids = inv.AddAnItem( 'Dumpling', 44 ); EquipItem(ids[0]); inv.AddAnItem('Clearing Potion', 2, true, false, false); GetHorseManager().RemoveAllItems(); ids.Clear(); ids = inv.AddAnItem('Horse Bag 2'); horseId = GetHorseManager().MoveItemToHorse(ids[0]); GetHorseManager().EquipItem(horseId); ids.Clear(); ids = inv.AddAnItem('Horse Blinder 2'); horseId = GetHorseManager().MoveItemToHorse(ids[0]); GetHorseManager().EquipItem(horseId); ids.Clear(); ids = inv.AddAnItem('Horse Saddle 2'); horseId = GetHorseManager().MoveItemToHorse(ids[0]); GetHorseManager().EquipItem(horseId); manager = theGame.GetJournalManager(); manager.GetActivatedOfType( 'CJournalCreature', ents ); for(i=0; i { manager.ActivateEntry(ents[i], JS_Inactive, false, true); } ents.Clear(); manager.GetActivatedOfType( 'CJournalCharacter', ents ); for(i=0; i { manager.ActivateEntry(ents[i], JS_Inactive, false, true); } ents.Clear(); manager.GetActivatedOfType( 'CJournalQuest', ents ); for(i=0; i { if( StrStartsWith(ents[i].baseName, "q60")) continue; manager.ActivateEntry(ents[i], JS_Inactive, false, true); } manager.ActivateEntryByScriptTag('TutorialAard', JS_Active); manager.ActivateEntryByScriptTag('TutorialAdrenaline', JS_Active); manager.ActivateEntryByScriptTag('TutorialAxii', JS_Active); manager.ActivateEntryByScriptTag('TutorialAxiiDialog', JS_Active); manager.ActivateEntryByScriptTag('TutorialCamera', JS_Active); manager.ActivateEntryByScriptTag('TutorialCamera_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialCiriBlink', JS_Active); manager.ActivateEntryByScriptTag('TutorialCiriCharge', JS_Active); manager.ActivateEntryByScriptTag('TutorialCiriStamina', JS_Active); manager.ActivateEntryByScriptTag('TutorialCounter', JS_Active); manager.ActivateEntryByScriptTag('TutorialDialogClose', JS_Active); manager.ActivateEntryByScriptTag('TutorialFallingRoll', JS_Active); manager.ActivateEntryByScriptTag('TutorialFocus', JS_Active); manager.ActivateEntryByScriptTag('TutorialFocusClues', JS_Active); manager.ActivateEntryByScriptTag('TutorialFocusClues', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseRoad', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseSpeed0', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseSpeed0_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseSpeed1', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseSpeed2', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseSummon', JS_Active); manager.ActivateEntryByScriptTag('TutorialHorseSummon_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialIgni', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalAlternateSings', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalBoatDamage', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalBoatMount', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalBuffs', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalCharDevLeveling', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalCharDevSkills', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalCrafting', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalCrossbow', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDialogGwint', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDialogShop', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDive', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDodge', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDodge_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDrawWeapon', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDrawWeapon_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalDurability', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalExplorations', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalExplorations_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalFastTravel', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalFocusRedObjects', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalGasClouds', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalHeavyAttacks', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalHorse', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalHorseStamina', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalJump', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalLightAttacks', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalLightAttacks_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMeditation', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMeditation_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMonsterThreatLevels', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMovement', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMovement_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMutagenIngredient', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalMutagenPotion', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalOils', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalPetards', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalPotions', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalPotions_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalQuestArea', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalRadial', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalRifts', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalRun', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalShopDescription', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalSignCast', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalSignCast_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalSpecialAttacks', JS_Active); manager.ActivateEntryByScriptTag('TutorialJournalStaminaExploration', JS_Active); manager.ActivateEntryByScriptTag('TutorialJumpHang', JS_Active); manager.ActivateEntryByScriptTag('TutorialLadder', JS_Active); manager.ActivateEntryByScriptTag('TutorialLadderMove', JS_Active); manager.ActivateEntryByScriptTag('TutorialLadderMove_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialObjectiveSwitching', JS_Active); manager.ActivateEntryByScriptTag('TutorialOxygen', JS_Active); manager.ActivateEntryByScriptTag('TutorialParry', JS_Active); manager.ActivateEntryByScriptTag('TutorialPOIUncovered', JS_Active); manager.ActivateEntryByScriptTag('TutorialQuen', JS_Active); manager.ActivateEntryByScriptTag('TutorialRoll', JS_Active); manager.ActivateEntryByScriptTag('TutorialRoll_pad', JS_Active); manager.ActivateEntryByScriptTag('TutorialSpeedPairing', JS_Active); manager.ActivateEntryByScriptTag('TutorialSprint', JS_Active); manager.ActivateEntryByScriptTag('TutorialStaminaSigns', JS_Active); manager.ActivateEntryByScriptTag('TutorialStealing', JS_Active); manager.ActivateEntryByScriptTag('TutorialSwimmingSpeed', JS_Active); manager.ActivateEntryByScriptTag('TutorialTimedChoiceDialog', JS_Active); manager.ActivateEntryByScriptTag('TutorialYrden', JS_Active); FactsAdd('kill_base_tutorials'); theGame.GetTutorialSystem().RemoveAllQueuedTutorials(); FactsAdd('standalone_ep1'); FactsRemove("StandAloneEP1"); theGame.GetJournalManager().ForceUntrackingQuestForEP1Savegame(); } final function Debug_FocusBoyFocusGain() { var focusGain : float; focusGain = FactsQuerySum( "debug_fact_focus_boy" ) ; GainStat( BCS_Focus, focusGain ); } public final function StandaloneEp2_1() { var i, inc, quantityLow, randLow, quantityMedium, randMedium, quantityHigh, randHigh, startingMoney : int; var pam : W3PlayerAbilityManager; var ids : array; var STARTING_LEVEL : int; FactsAdd( "StandAloneEP2", 1 ); inv.RemoveAllItems(); inv.AddAnItem( 'Illusion Medallion', 1, true, true, false ); inv.AddAnItem( 'q103_safe_conduct', 1, true, true, false ); theGame.GetGamerProfile().ClearAllAchievementsForEP2(); levelManager.Hack_EP2StandaloneLevelShrink( 35 ); levelManager.ResetCharacterDev(); pam = ( W3PlayerAbilityManager )abilityManager; if( pam ) { pam.ResetCharacterDev(); } levelManager.SetFreeSkillPoints( levelManager.GetLevel() - 1 + 11 ); inv.AddAnItem( 'Mutagen red', 4 ); inv.AddAnItem( 'Mutagen green', 4 ); inv.AddAnItem( 'Mutagen blue', 4 ); inv.AddAnItem( 'Lesser mutagen red', 2 ); inv.AddAnItem( 'Lesser mutagen green', 2 ); inv.AddAnItem( 'Lesser mutagen blue', 2 ); inv.AddAnItem( 'Greater mutagen red', 2 ); inv.AddAnItem( 'Greater mutagen green', 2 ); inv.AddAnItem( 'Greater mutagen blue', 2 ); startingMoney = 20000; if( GetMoney() > startingMoney ) { RemoveMoney( GetMoney() - startingMoney ); } else { AddMoney( 20000 - GetMoney() ); } ids.Clear(); ids = inv.AddAnItem( 'EP2 Standalone Starting Armor' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'EP2 Standalone Starting Boots' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'EP2 Standalone Starting Gloves' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'EP2 Standalone Starting Pants' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'EP2 Standalone Starting Steel Sword' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'EP2 Standalone Starting Silver Sword' ); EquipItem( ids[0] ); inv.AddAnItem( 'Torch', 1, true, true, false ); quantityLow = 1; randLow = 3; quantityMedium = 4; randMedium = 4; quantityHigh = 8; randHigh = 6; inv.AddAnItem( 'Alghoul bone marrow',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Amethyst dust',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Arachas eyes',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Arachas venom',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Basilisk hide',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Basilisk venom',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Bear pelt',quantityHigh+RandRange( randHigh ) ); inv.AddAnItem( 'Berserker pelt',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Coal',quantityHigh+RandRange( randHigh ) ); inv.AddAnItem( 'Cotton',quantityHigh+RandRange( randHigh ) ); inv.AddAnItem( 'Deer hide',quantityHigh+RandRange( randHigh ) ); inv.AddAnItem( 'Diamond dust',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Drowned dead tongue',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Drowner brain',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Endriag chitin plates',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Endriag embryo',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Ghoul blood',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Goat hide',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Hag teeth',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Hardened leather',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Hardened timber',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Harpy feathers',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Horse hide',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Necrophage skin',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Nekker blood',quantityHigh+RandRange( randHigh ) ); inv.AddAnItem( 'Nekker heart',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Phosphorescent crystal',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Pig hide',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Rabbit pelt',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Rotfiend blood',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Sapphire dust',quantityLow+RandRange( randLow ) ); inv.AddAnItem( 'Specter dust',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Water essence',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Wolf liver',quantityHigh+RandRange( randHigh ) ); inv.AddAnItem( 'Wolf pelt',quantityMedium+RandRange( randMedium ) ); inv.AddAnItem( 'Alcohest', 5 ); inv.AddAnItem( 'Dwarven spirit', 5 ); ids.Clear(); ids = inv.AddAnItem( 'Crossbow 5' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'Blunt Bolt', 100 ); EquipItem( ids[0] ); inv.AddAnItem( 'Broadhead Bolt', 100 ); inv.AddAnItem( 'Split Bolt', 100 ); RemoveAllAlchemyRecipes(); RemoveAllCraftingSchematics(); AddAlchemyRecipe( 'Recipe for Petris Philtre 2' ); AddAlchemyRecipe( 'Recipe for Swallow 1' ); AddAlchemyRecipe( 'Recipe for Tawny Owl 1' ); AddAlchemyRecipe( 'Recipe for White Gull 1' ); AddAlchemyRecipe( 'Recipe for Beast Oil 1' ); AddAlchemyRecipe( 'Recipe for Cursed Oil 1' ); AddAlchemyRecipe( 'Recipe for Hanged Man Venom 1' ); AddAlchemyRecipe( 'Recipe for Hybrid Oil 1' ); AddAlchemyRecipe( 'Recipe for Insectoid Oil 2' ); AddAlchemyRecipe( 'Recipe for Magicals Oil 1' ); AddAlchemyRecipe( 'Recipe for Necrophage Oil 1' ); AddAlchemyRecipe( 'Recipe for Specter Oil 1' ); AddAlchemyRecipe( 'Recipe for Vampire Oil 2' ); AddAlchemyRecipe( 'Recipe for Draconide Oil 2' ); AddAlchemyRecipe( 'Recipe for Ogre Oil 1' ); AddAlchemyRecipe( 'Recipe for Relic Oil 1' ); AddAlchemyRecipe( 'Recipe for Beast Oil 2' ); AddAlchemyRecipe( 'Recipe for Cursed Oil 2' ); AddAlchemyRecipe( 'Recipe for Hanged Man Venom 2' ); AddAlchemyRecipe( 'Recipe for Hybrid Oil 2' ); AddAlchemyRecipe( 'Recipe for Insectoid Oil 2' ); AddAlchemyRecipe( 'Recipe for Magicals Oil 2' ); AddAlchemyRecipe( 'Recipe for Necrophage Oil 2' ); AddAlchemyRecipe( 'Recipe for Specter Oil 2' ); AddAlchemyRecipe( 'Recipe for Vampire Oil 2' ); AddAlchemyRecipe( 'Recipe for Draconide Oil 2' ); AddAlchemyRecipe( 'Recipe for Ogre Oil 2' ); AddAlchemyRecipe( 'Recipe for Relic Oil 2' ); AddAlchemyRecipe( 'Recipe for Dancing Star 1' ); AddAlchemyRecipe( 'Recipe for Dwimeritum Bomb 1' ); AddAlchemyRecipe( 'Recipe for Grapeshot 1' ); AddAlchemyRecipe( 'Recipe for Samum 1' ); AddAlchemyRecipe( 'Recipe for White Frost 1' ); AddAlchemyRecipe( 'Recipe for Dwarven spirit 1' ); AddAlchemyRecipe( 'Recipe for Alcohest 1' ); AddAlchemyRecipe( 'Recipe for White Gull 1' ); AddStartingSchematics(); ids.Clear(); ids = inv.AddAnItem( 'Swallow 2' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'Thunderbolt 2' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'Tawny Owl 2' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'Grapeshot 2' ); EquipItem( ids[0] ); ids.Clear(); ids = inv.AddAnItem( 'Samum 2' ); EquipItem( ids[0] ); inv.AddAnItem( 'Dwimeritum Bomb 1' ); inv.AddAnItem( 'Dragons Dream 1' ); inv.AddAnItem( 'Silver Dust Bomb 1' ); inv.AddAnItem( 'White Frost 2' ); inv.AddAnItem( 'Devils Puffball 2' ); inv.AddAnItem( 'Dancing Star 2' ); inv.AddAnItem( 'Beast Oil 1' ); inv.AddAnItem( 'Cursed Oil 1' ); inv.AddAnItem( 'Hanged Man Venom 2' ); inv.AddAnItem( 'Hybrid Oil 2' ); inv.AddAnItem( 'Insectoid Oil 2' ); inv.AddAnItem( 'Magicals Oil 1' ); inv.AddAnItem( 'Necrophage Oil 2' ); inv.AddAnItem( 'Ogre Oil 1' ); inv.AddAnItem( 'Specter Oil 1' ); inv.AddAnItem( 'Vampire Oil 2' ); inv.AddAnItem( 'Draconide Oil 2' ); inv.AddAnItem( 'Relic Oil 1' ); inv.AddAnItem( 'Black Blood 1' ); inv.AddAnItem( 'Blizzard 1' ); inv.AddAnItem( 'Cat 2' ); inv.AddAnItem( 'Full Moon 1' ); inv.AddAnItem( 'Golden Oriole 1' ); inv.AddAnItem( 'Killer Whale 1' ); inv.AddAnItem( 'Maribor Forest 1' ); inv.AddAnItem( 'Petris Philtre 2' ); inv.AddAnItem( 'White Gull 1', 3 ); inv.AddAnItem( 'White Honey 2' ); inv.AddAnItem( 'White Raffards Decoction 1' ); inv.AddAnItem( 'Mutagen 17' ); inv.AddAnItem( 'Mutagen 19' ); inv.AddAnItem( 'Mutagen 27' ); inv.AddAnItem( 'Mutagen 26' ); inv.AddAnItem( 'weapon_repair_kit_1', 5 ); inv.AddAnItem( 'weapon_repair_kit_2', 3 ); inv.AddAnItem( 'armor_repair_kit_1', 5 ); inv.AddAnItem( 'armor_repair_kit_2', 3 ); quantityMedium = 2; quantityLow = 1; inv.AddAnItem( 'Rune stribog lesser', quantityMedium ); inv.AddAnItem( 'Rune stribog', quantityLow ); inv.AddAnItem( 'Rune dazhbog lesser', quantityMedium ); inv.AddAnItem( 'Rune dazhbog', quantityLow ); inv.AddAnItem( 'Rune devana lesser', quantityMedium ); inv.AddAnItem( 'Rune devana', quantityLow ); inv.AddAnItem( 'Rune zoria lesser', quantityMedium ); inv.AddAnItem( 'Rune zoria', quantityLow ); inv.AddAnItem( 'Rune morana lesser', quantityMedium ); inv.AddAnItem( 'Rune morana', quantityLow ); inv.AddAnItem( 'Rune triglav lesser', quantityMedium ); inv.AddAnItem( 'Rune triglav', quantityLow ); inv.AddAnItem( 'Rune svarog lesser', quantityMedium ); inv.AddAnItem( 'Rune svarog', quantityLow ); inv.AddAnItem( 'Rune veles lesser', quantityMedium ); inv.AddAnItem( 'Rune veles', quantityLow ); inv.AddAnItem( 'Rune perun lesser', quantityMedium ); inv.AddAnItem( 'Rune perun', quantityLow ); inv.AddAnItem( 'Rune elemental lesser', quantityMedium ); inv.AddAnItem( 'Rune elemental', quantityLow ); inv.AddAnItem( 'Glyph aard lesser', quantityMedium ); inv.AddAnItem( 'Glyph aard', quantityLow ); inv.AddAnItem( 'Glyph axii lesser', quantityMedium ); inv.AddAnItem( 'Glyph axii', quantityLow ); inv.AddAnItem( 'Glyph igni lesser', quantityMedium ); inv.AddAnItem( 'Glyph igni', quantityLow ); inv.AddAnItem( 'Glyph quen lesser', quantityMedium ); inv.AddAnItem( 'Glyph quen', quantityLow ); inv.AddAnItem( 'Glyph yrden lesser', quantityMedium ); inv.AddAnItem( 'Glyph yrden', quantityLow ); StandaloneEp2_2(); } public final function StandaloneEp2_2() { var horseId : SItemUniqueId; var ids : array; var ents : array< CJournalBase >; var i : int; var manager : CWitcherJournalManager; inv.AddAnItem( 'Cows milk', 20 ); ids.Clear(); ids = inv.AddAnItem( 'Dumpling', 44 ); EquipItem( ids[0] ); inv.AddAnItem( 'Clearing Potion', 2, true, false, false ); GetHorseManager().RemoveAllItems(); ids.Clear(); ids = inv.AddAnItem( 'Horse Bag 2' ); horseId = GetHorseManager( ).MoveItemToHorse( ids[0] ); GetHorseManager().EquipItem( horseId ); ids.Clear(); ids = inv.AddAnItem( 'Horse Blinder 2' ); horseId = GetHorseManager().MoveItemToHorse( ids[0] ); GetHorseManager().EquipItem( horseId ); ids.Clear(); ids = inv.AddAnItem( 'Horse Saddle 2' ); horseId = GetHorseManager().MoveItemToHorse( ids[0] ); GetHorseManager().EquipItem( horseId ); manager = theGame.GetJournalManager(); manager.GetActivatedOfType( 'CJournalCreature', ents ); for(i=0; i { manager.ActivateEntry( ents[i], JS_Inactive, false, true ); } ents.Clear(); manager.GetActivatedOfType( 'CJournalCharacter', ents ); for(i=0; i { manager.ActivateEntry( ents[i], JS_Inactive, false, true ); } ents.Clear(); manager.GetActivatedOfType( 'CJournalQuest', ents ); for(i=0; i { if( StrStartsWith( ents[i].baseName, "q60" ) ) continue; manager.ActivateEntry( ents[i], JS_Inactive, false, true ); } manager.ActivateEntryByScriptTag( 'TutorialAard', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialAdrenaline', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialAxii', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialAxiiDialog', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialCamera', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialCamera_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialCiriBlink', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialCiriCharge', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialCiriStamina', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialCounter', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialDialogClose', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialFallingRoll', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialFocus', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialFocusClues', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialFocusClues', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseRoad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseSpeed0', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseSpeed0_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseSpeed1', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseSpeed2', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseSummon', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialHorseSummon_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialIgni', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalAlternateSings', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalBoatDamage', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalBoatMount', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalBuffs', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalCharDevLeveling', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalCharDevSkills', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalCrafting', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalCrossbow', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDialogGwint', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDialogShop', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDive', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDodge', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDodge_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDrawWeapon', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDrawWeapon_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalDurability', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalExplorations', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalExplorations_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalFastTravel', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalFocusRedObjects', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalGasClouds', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalHeavyAttacks', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalHorse', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalHorseStamina', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalJump', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalLightAttacks', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalLightAttacks_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMeditation', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMeditation_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMonsterThreatLevels', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMovement', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMovement_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMutagenIngredient', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalMutagenPotion', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalOils', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalPetards', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalPotions', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalPotions_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalQuestArea', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalRadial', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalRifts', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalRun', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalShopDescription', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalSignCast', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalSignCast_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalSpecialAttacks', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJournalStaminaExploration', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialJumpHang', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialLadder', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialLadderMove', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialLadderMove_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialObjectiveSwitching', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialOxygen', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialParry', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialPOIUncovered', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialQuen', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialRoll', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialRoll_pad', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialSpeedPairing', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialSprint', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialStaminaSigns', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialStealing', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialSwimmingSpeed', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialTimedChoiceDialog', JS_Active ); manager.ActivateEntryByScriptTag( 'TutorialYrden', JS_Active ); inv.AddAnItem( 'Geralt Shirt', 1 ); inv.AddAnItem( 'Thread', 13 ); inv.AddAnItem( 'String', 9 ); inv.AddAnItem( 'Linen', 4 ); inv.AddAnItem( 'Silk', 6 ); inv.AddAnItem( 'Nigredo', 3 ); inv.AddAnItem( 'Albedo', 1 ); inv.AddAnItem( 'Rubedo', 1 ); inv.AddAnItem( 'Rebis', 1 ); inv.AddAnItem( 'Dog tallow', 4 ); inv.AddAnItem( 'Lunar shards', 3 ); inv.AddAnItem( 'Quicksilver solution', 5 ); inv.AddAnItem( 'Aether', 1 ); inv.AddAnItem( 'Optima mater', 3 ); inv.AddAnItem( 'Fifth essence', 2 ); inv.AddAnItem( 'Hardened timber', 6 ); inv.AddAnItem( 'Fur square', 1 ); inv.AddAnItem( 'Leather straps', 11 ); inv.AddAnItem( 'Leather squares', 6 ); inv.AddAnItem( 'Leather', 3 ); inv.AddAnItem( 'Hardened leather', 14 ); inv.AddAnItem( 'Chitin scale', 8 ); inv.AddAnItem( 'Draconide leather', 5 ); inv.AddAnItem( 'Infused draconide leather', 0 ); inv.AddAnItem( 'Steel ingot', 5 ); inv.AddAnItem( 'Dark iron ore', 2 ); inv.AddAnItem( 'Dark iron ingot', 3 ); inv.AddAnItem( 'Dark iron plate', 1 ); inv.AddAnItem( 'Dark steel ingot', 10 ); inv.AddAnItem( 'Dark steel plate', 6 ); inv.AddAnItem( 'Silver ore', 2 ); inv.AddAnItem( 'Silver ingot', 6 ); inv.AddAnItem( 'Meteorite ore', 3 ); inv.AddAnItem( 'Meteorite ingot', 3 ); inv.AddAnItem( 'Meteorite plate', 2 ); inv.AddAnItem( 'Meteorite silver ingot', 6 ); inv.AddAnItem( 'Meteorite silver plate', 5 ); inv.AddAnItem( 'Orichalcum ingot', 0 ); inv.AddAnItem( 'Orichalcum plate', 1 ); inv.AddAnItem( 'Dwimeryte ingot', 6 ); inv.AddAnItem( 'Dwimeryte plate', 5 ); inv.AddAnItem( 'Dwimeryte enriched ingot', 0 ); inv.AddAnItem( 'Dwimeryte enriched plate', 0 ); inv.AddAnItem( 'Emerald dust', 0 ); inv.AddAnItem( 'Ruby dust', 4 ); inv.AddAnItem( 'Ruby', 2 ); inv.AddAnItem( 'Ruby flawless', 1 ); inv.AddAnItem( 'Sapphire dust', 0 ); inv.AddAnItem( 'Sapphire', 0 ); inv.AddAnItem( 'Monstrous brain', 8 ); inv.AddAnItem( 'Monstrous blood', 14 ); inv.AddAnItem( 'Monstrous bone', 9 ); inv.AddAnItem( 'Monstrous claw', 14 ); inv.AddAnItem( 'Monstrous dust', 9 ); inv.AddAnItem( 'Monstrous ear', 5 ); inv.AddAnItem( 'Monstrous egg', 1 ); inv.AddAnItem( 'Monstrous eye', 10 ); inv.AddAnItem( 'Monstrous essence', 7 ); inv.AddAnItem( 'Monstrous feather', 8 ); inv.AddAnItem( 'Monstrous hair', 12 ); inv.AddAnItem( 'Monstrous heart', 7 ); inv.AddAnItem( 'Monstrous hide', 4 ); inv.AddAnItem( 'Monstrous liver', 5 ); inv.AddAnItem( 'Monstrous plate', 1 ); inv.AddAnItem( 'Monstrous saliva', 6 ); inv.AddAnItem( 'Monstrous stomach', 3 ); inv.AddAnItem( 'Monstrous tongue', 5 ); inv.AddAnItem( 'Monstrous tooth', 9 ); inv.AddAnItem( 'Venom extract', 0 ); inv.AddAnItem( 'Siren vocal cords', 1 ); SelectQuickslotItem( EES_RangedWeapon ); FactsAdd( 'kill_base_tutorials' ); theGame.GetTutorialSystem().RemoveAllQueuedTutorials(); FactsAdd( 'standalone_ep2' ); FactsRemove( "StandAloneEP2" ); theGame.GetJournalManager().ForceUntrackingQuestForEP1Savegame(); } //zur13 public function SSS_GetEquippedMutationType() : EPlayerMutationType { //return first equipped mutation var equippedMutations : array< EPlayerMutationType >; equippedMutations = GetEquippedMutationType(); if(equippedMutations.Size()>0) { return equippedMutations[0]; } return EPMT_None; } } exec function fuqfep1() { theGame.GetJournalManager().ForceUntrackingQuestForEP1Savegame(); } function GetWitcherPlayer() : W3PlayerWitcher { return (W3PlayerWitcher)thePlayer; }();>();>();>();>();>();>;>();>();>();>();>();>();>();>;>;>;>;>;>;>;>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>();>;>();>();>();>();>[/spoiler] [spoiler]r4player: statemachine abstract import class CR4Player extends CPlayer { // BEHAVIOR INITIALIZATION protected var pcGamePlayInitialized : bool; // MS: hack variable to fix Tpose when initially spawning Geralt (Consult Tomsin) // PC Controls private var pcMode : bool; // MS: Use control/camera modifications for keyboard/mouse default pcMode = true; // COMBAT MECHANICS protected saved var weaponHolster : WeaponHolster; // Makes Geralt holster and unholster the swords public var rangedWeapon : Crossbow; // Handles ranged weapons public var crossbowDontPopStateHack : bool; default crossbowDontPopStateHack = false; private var hitReactTransScale : float; //dynamic scale for npc's hitreaction animation translation to force CloseCombat private var bIsCombatActionAllowed : bool; private var currentCombatAction : EBufferActionType; private var uninterruptedHitsCount : int; //amount of uninterrupted hints performed by the player (gets reset when we get hit or stop attacking etc.) private var uninterruptedHitsCameraStarted : bool; //set to true once we enable the uninterrupted hits camera effect private var uninterruptedHitsCurrentCameraEffect : name; //currently used camera blurr effect for uninterrupted hits private var counterTimestamps : array; //times when player pressed counter attack button - we check it later to prevent spamming private var hitReactionEffect : bool; //blurr private var lookAtPosition : Vector; //Position that Geralt is looking at, also where he will shoot private var orientationTarget : EOrientationTarget; private var customOrientationTarget : EOrientationTarget; protected var customOrientationStack : array; public var delayOrientationChange : bool; protected var delayCameraOrientationChange : bool; private var actionType : int; // 0 = sign, 1 = guard, 2 = specialAttack, 3 = throwItem private var customOrientationStackIndex : int; //Used by Player only: will disable the previous combat action's orientation target and add to the stack everytime he performs a new combat action private var emptyMoveTargetTimer : float; private var onlyOneEnemyLeft : bool; public var isInFinisher : bool; private var finisherTarget : CGameplayEntity; private var combatStance : EPlayerCombatStance; public var approachAttack : int; //Enable/Disable approach attack prototype, 0 = enabled, 1 = disabled with no far attack limit, 2 = disabled with far attack limit default approachAttack = 1; protected var specialAttackCamera : bool; private var specialAttackTimeRatio : float; public saved var itemsPerLevel : array; public var itemsPerLevelGiven : array; private var playerTickTimerPhase : int; default playerTickTimerPhase = 0; protected var evadeHeading : float; public var vehicleCbtMgrAiming : bool; //MS: hack variable to pass vehicleCbtMgr aiming variable to UseGenericVehicle public var specialHeavyChargeDuration : float; //duration of charge-up event public var specialHeavyStartEngineTime : EngineTime; //timestamp of when the charge-up started public var playedSpecialAttackMissingResourceSound : bool; //if missing resource sound was played or not (used in loop) public function SetPlayedSpecialAttackMissingResourceSound(b : bool) {playedSpecialAttackMissingResourceSound = b;} public var counterCollisionGroupNames : array; public saved var lastInstantKillTime : GameTime; // Save locks private var noSaveLockCombatActionName : string; default noSaveLockCombatActionName = 'combat_action'; private var noSaveLockCombatAction : int; private var deathNoSaveLock : int; private var noSaveLock : int; //new game plus protected saved var newGamePlusInitialized : bool; default newGamePlusInitialized = false; // action buffer protected var BufferAllSteps : bool; protected var BufferCombatAction : EBufferActionType; protected var BufferButtonStage : EButtonStage; default BufferAllSteps = false; default customOrientationTarget = OT_None; default hitReactionEffect = true; default uninterruptedHitsCount = 0; default uninterruptedHitsCameraStarted = false; default customOrientationStackIndex = -1; // CRITICAL STATES private var keepRequestingCriticalAnimStart : bool; //set to true while we are trying to start critical anim default keepRequestingCriticalAnimStart = false; // EXPLORATION private var currentCustomAction : EPlayerExplorationAction; public var substateManager : CExplorationStateManager; protected var isOnBoat : bool; //set to true if player is on boat (but not necessarily sailing, but e.g. standing) protected var isInShallowWater : bool; public var medallion : W3MedallionFX; protected var lastMedallionEffect : float; private var isInRunAnimation : bool; public var interiorTracker :CPlayerInteriorTracker; public var m_SettlementBlockCanter : int; // FISTFIGHT MINIGAME private var fistFightMinigameEnabled : bool; private var isFFMinigameToTheDeath : bool; private var FFMinigameEndsithBS : bool; public var fistFightTeleportNode : CNode; public var isStartingFistFightMinigame : bool; public var GeraltMaxHealth : float; public var fistsItems : array< SItemUniqueId >; default FFMinigameEndsithBS = false; default fistFightMinigameEnabled = false; default isFFMinigameToTheDeath = false; // GWINT MINIGAME private var gwintAiDifficulty : EGwintDifficultyMode; default gwintAiDifficulty = EGDM_Easy; private var gwintAiAggression : EGwintAggressionMode; default gwintAiAggression = EGAM_Defensive; private var gwintMinigameState : EMinigameState; default gwintMinigameState = EMS_None; // HORSE import private var horseWithInventory : EntityHandle; // if spawned handle is valid ( horse with inventory ) private var currentlyMountedHorse : CNewNPC; private var horseSummonTimeStamp : float; private saved var isHorseRacing : bool; private var horseCombatSlowMo : bool; default isHorseRacing = false; default horseCombatSlowMo = true; // HUD FIXME - shouldn't this all be in hud / ui rather than player? private var HudMessages : array ; //#B change to struct with message type, message duration etc protected var fShowToLowStaminaIndication : float; public var showTooLowAdrenaline : bool; private var HAXE3Container : W3Container; //#B temp for E3 private var HAXE3bAutoLoot: bool; //#B temp for E3 private var bShowHud : bool; private var dodgeFeedbackTarget : CActor; default HAXE3bAutoLoot = false; default fShowToLowStaminaIndication = 0.0f; default bShowHud = true; saved var displayedQuestsGUID : array< CGUID >; // #B moved here because saved in journal doesn't work. saved var rewardsMultiplier : array< SRewardMultiplier >; // #B moved here because saved in journal doesn't work.s saved var glossaryImageOverride : array< SGlossaryImageOverride >; // #B moved here because saved in journal doesn't work.s // INPUT private var prevRawLeftJoyRot : float; protected var explorationInputContext : name; protected var combatInputContext : name; protected var combatFistsInputContext : name; // INTERACTIONS private var isInsideInteraction : bool; //set to true when player is inside any interaction range, used to prioritize input private var isInsideHorseInteraction : bool; public var horseInteractionSource : CEntity; public var nearbyLockedContainersNoKey : array; //to update tooltip if player is close to a locked container and is THEN given a key // MOVEMENT private var bMoveTargetChangeAllowed : bool; default bMoveTargetChangeAllowed = true; private var moveAdj : CMovementAdjustor; private var defaultLocomotionController : CR4LocomotionPlayerControllerScript; //private var isFollowing : bool; //private var followingStartTime : float; private var canFollowNpc : bool; private var actorToFollow : CActor; public var terrainPitch : float; public var steepSlopeNormalPitch : float; default steepSlopeNormalPitch = 65.f; public var disableSprintTerrainPitch : float; default disableSprintTerrainPitch = 54.f; private var submergeDepth : float; private var m_useSelectedItemIfSpawned : bool; default m_useSelectedItemIfSpawned = false; // Used only in WaitForItemSpawnAndProccesTask var navQuery : CNavigationReachabilityQueryInterface; // BARBER public saved var rememberedCustomHead : name; // EPISODE1 public saved var proudWalk : bool; private var etherealCount : int; default etherealCount = 0; // PHANTOM WEAPON private var phantomWeaponMgr : CPhantomWeaponManager; /*public var bonePositionCam : Vector; public function SetBonePositionCam( pos : Vector ) { bonePositionCam = pos; }*/ function EnablePCMode( flag : bool ) { pcMode = flag; } public function IsPCModeEnabled() : bool { return pcMode && theInput.LastUsedPCInput(); } public function ShouldUsePCModeTargeting() : bool { return IsPCModeEnabled() && !lastAxisInputIsMovement; } public function SetDodgeFeedbackTarget( target : CActor ) { dodgeFeedbackTarget = target; } public function GetDodgeFeedbackTarget() : CActor { return dodgeFeedbackTarget; } public function SetSubmergeDepth( depth : float ) { submergeDepth = depth; } public function GetSubmergeDepth() : float { return submergeDepth; } // ONELINERS editable var delayBetweenIllusionOneliners : float; hint delayBetweenIllusionOneliners = "delay in secs between oneliners about illusionary objects"; default delayBetweenIllusionOneliners = 5; // Battlecry private var battlecry_timeForNext : float; private var battlecry_delayMin : float; default battlecry_delayMin = 15; private var battlecry_delayMax : float; default battlecry_delayMax = 60; private var battlecry_lastTry : name; // Weather private var previousWeather : name; private var previousRainStrength : float; //OTHER protected var receivedDamageInCombat : bool; //set when you got hit protected var prevDayNightIsNight : bool; //Day-Night cycle check - value of previous check public var failedFundamentalsFirstAchievementCondition : bool; //achievement private var spawnedTime : float; public var currentMonsterHuntInvestigationArea : W3MonsterHuntInvestigationArea; private var isPerformingPhaseChangeAnimation : bool; // flag for suppressing game camera update during synced animation in eredin fight default isPerformingPhaseChangeAnimation = false; default receivedDamageInCombat = false; // PLAYER MODE public var playerMode : W3PlayerMode; // QUICKSLOTS protected saved var selectedItemId : SItemUniqueId; //id of item selected from quickslots protected saved var blockedRadialSlots : array < SRadialSlotDef >; // radial menu slots blocked by different sources // SOFT LOCK TARGETING public var enemyCollectionDist : float; public var findMoveTargetDistMin : float; //distance from player to get softlocked targets public var findMoveTargetDistMax : float; //distance from player that target gets disengaged from soft lock private var findMoveTargetScaledFrame : float; //xaxis scale to find non-hostile targets when stationary public var interactDist : float; //distance from player to attack or interact with a non-hostile npc protected var bCanFindTarget : bool; private var bIsConfirmingEmptyTarget : bool; private var displayTarget : CGameplayEntity; //entity to show health bar on hud; private var isShootingFriendly : bool; default findMoveTargetDistMax = 18.f; default findMoveTargetScaledFrame = 0.5f; default interactDist = 3.5f; //Target Selection private var currentSelectedTarget : CActor; private var selectedTargetToConfirm : CActor; private var bConfirmTargetTimerIsEnabled : bool; // THROWABLES public saved var thrownEntityHandle : EntityHandle; //entity of currently thrown item (in aiming) private var isThrowingItemWithAim : bool; private saved var isThrowingItem : bool; //used for aim mode to check if we're in throwing logic private var isThrowHoldPressed : bool; // CROSSBOW private var isAimingCrossbow : bool; default isThrowingItemWithAim = false; // AIMING MODE public var playerAiming : PlayerAiming; // DISMEMBERMENT public var forceDismember : bool; public var forceDismemberName : name; public var forceDismemberChance : int; public var forceDismemberExplosion : bool; // FINISHER private var finisherVictim : CActor; public var forceFinisher : bool; public var forceFinisherAnimName : name; public var forceFinisherChance : int; public var forcedStance : bool; // WEAPON COLLISION FX private var m_WeaponFXCollisionGroupNames : array ; private var m_CollisionEffect : CEntity; private var m_LastWeaponTipPos : Vector; private var m_CollisionFxTemplate : CEntityTemplate; private var m_RefreshWeaponFXType : bool; private var m_PlayWoodenFX : bool; // POSTERS private var m_activePoster : W3Poster; public function SetActivePoster ( poster : W3Poster ) { m_activePoster = poster; } public function RemoveActivePoster () { m_activePoster = NULL; } public function GetActivePoster () : W3Poster { return m_activePoster; } // SAVE / LOAD //private saved var safePositionStored: bool; default safePositionStored = false; //private saved var lastSafePosition : Vector; //private saved var lastSafeRotation : EulerAngles; public var horseOnNavMesh : bool; default horseOnNavMesh = true; public function SetHorseNav( val : bool ) { horseOnNavMesh = val; } // TEST public var testAdjustRequestedMovementDirection : bool; // TEST default testAdjustRequestedMovementDirection = false; // State default autoState = 'Exploration'; /////////////////////////////////////////////////////////////////////////// /////////////////// IMPORTED C++ FUNCTIONS ////////////////////////////// /////////////////////////////////////////////////////////////////////////// // All following functions give cached data from previous frame import final function GetEnemiesInRange( out enemies : array< CActor > ); import final function GetVisibleEnemies( out enemies : array< CActor > ); import final function IsEnemyVisible( enemy : CActor ) : bool; // Set this up in order to use above functions and get the proper data import final function SetupEnemiesCollection( range, heightTolerance : float, maxEnemies : int, optional tag : name, optional flags : int ); // please combine EScriptQueryFlags - FLAG_ExcludePlayer is always on import final function IsInInterior() : bool; import final function IsInSettlement() : bool; import final function EnterSettlement( isEntering : bool ); import final function ActionDirectControl( controller : CR4LocomotionDirectController ) : bool; import final function SetPlayerTarget( target : CActor ); import final function SetPlayerCombatTarget( target : CActor ); import final function ObtainTicketFromCombatTarget( ticketName : CName, ticketsCount : int ); import final function FreeTicketAtCombatTarget(); import final function SetScriptMoveTarget( target : CActor ); import final function GetRiderData() : CAIStorageRiderData; import final function SetIsInCombat( inCombat : bool ); import final function SaveLastMountedHorse( mountedHorse : CActor ); import final function SetBacklightFromHealth( healthPercentage : float ); import private final function SetBacklightColor( color : Vector ); import final function GetCombatDataComponent() : CCombatDataComponent; import final function GetTemplatePathAndAppearance( out templatePath : string, out appearance : name ); import final function HACK_BoatDismountPositionCorrection( slotPos : Vector ); import final function HACK_ForceGetBonePosition( boneIndex : int ) : Vector; public function GetLevel() : int { return 0; } /////////////////////////////////////////////////////////////////////////// // (new) targeting var targeting : CR4PlayerTargeting; var targetingPrecalcs : SR4PlayerTargetingPrecalcs; var targetingIn : SR4PlayerTargetingIn; var targetingOut : SR4PlayerTargetingOut; var useNativeTargeting : bool; default useNativeTargeting = true; var visibleActors : array< CActor >; var visibleActorsTime : array< float >; /////////////////////////////////////////////////////////////////////////// event OnSpawned( spawnData : SEntitySpawnData ) { var atts : array; var skill : ESkill; var i : int; var item : SItemUniqueId; AddAnimEventCallback('ThrowHoldTest', 'OnAnimEvent_ThrowHoldTest'); AddAnimEventCallback('OnWeaponDrawReady', 'OnAnimEvent_OnWeaponDrawReady'); AddAnimEventCallback('OnWeaponHolsterReady', 'OnAnimEvent_OnWeaponHolsterReady'); AddAnimEventCallback('AllowTempLookAt', 'OnAnimEvent_AllowTempLookAt'); AddAnimEventCallback('SlideToTarget', 'OnAnimEvent_SlideToTarget'); AddAnimEventCallback('PlayFinisherBlood', 'OnAnimEvent_PlayFinisherBlood'); AddAnimEventCallback('SlowMo', 'OnAnimEvent_SlowMo'); AddAnimEventCallback('BloodTrailForced', 'OnAnimEvent_BloodTrailForced'); AddAnimEventCallback('FadeOut', 'OnAnimEvent_FadeOut'); AddAnimEventCallback('FadeIn', 'OnAnimEvent_FadeIn'); AddAnimEventCallback('DisallowHitAnim', 'OnAnimEvent_DisallowHitAnim'); AddAnimEventCallback('AllowFall', 'OnAnimEvent_AllowFall'); AddAnimEventCallback('AllowFall2', 'OnAnimEvent_AllowFall2'); AddAnimEventCallback('DettachGround', 'OnAnimEvent_DettachGround'); AddAnimEventCallback('KillWithRagdoll', 'OnAnimEvent_KillWithRagdoll'); AddAnimEventCallback('pad_vibration', 'OnAnimEvent_pad_vibration'); AddAnimEventCallback('pad_vibration_light', 'OnAnimEvent_pad_vibration_light'); AddAnimEventCallback('RemoveBurning', 'OnAnimEvent_RemoveBurning'); AddAnimEventCallback('RemoveTangled', 'OnAnimEvent_RemoveTangled'); AddItemPerLevelList(); enemyCollectionDist = findMoveTargetDistMax; //give items if(!spawnData.restored && !((W3ReplacerCiri)this) ) { AddTimer('GiveStartingItems', 0.00001, true, , , true); if(!theGame.IsFinalBuild()) { //unlock skills for testing purposes AddAbility('GeraltSkills_Testing'); AddTimer('Debug_GiveTestingItems',0.0001,true); } } InitTargeting(); // After load if( spawnData.restored ) { // ED this line was not called before, because of extra if conditions regarding "safe position stored" but it was uncommented //OnUseSelectedItem(); } // Create the sword holster (it is a saved property, there is no need of re-creating it when playing from save) if ( !weaponHolster ) { weaponHolster = new WeaponHolster in this; } // temp workaround of not saving states: weaponHolster.Initialize( this, spawnData.restored ); if ( !interiorTracker ) { interiorTracker = new CPlayerInteriorTracker in this; } interiorTracker.Init( spawnData.restored ); super.OnSpawned( spawnData ); // Create medallion medallion = new W3MedallionFX in this; playerMode = new W3PlayerMode in this; playerMode.Initialize( this ); // Initialize Aiming Mode playerAiming = new PlayerAiming in this; playerAiming.Initialize( this ); // Initialize reachability query navQuery = new CNavigationReachabilityQueryInterface in this; // Start looking for soft-lock targets EnableFindTarget( true ); AddTimer( 'CombatCheck', 0.2f, true ); // Get the exploration state manager component substateManager = ( CExplorationStateManager ) GetComponentByClassName( 'CExplorationStateManager' ); findMoveTargetDist = findMoveTargetDistMax; SetupEnemiesCollection( enemyCollectionDist, findMoveTargetDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors ); //for geralt-replacer switching inputHandler.RemoveLocksOnSpawn(); // Player has the lowest push priority ((CActor) this ).SetInteractionPriority( IP_Prio_0 ); prevDayNightIsNight = theGame.envMgr.IsNight(); CheckDayNightCycle(); // Debug EnableVisualDebug( SHOW_AI, true ); //oneliners delay FactsRemove("blocked_illusion_oneliner"); SetFailedFundamentalsFirstAchievementCondition(false); m_CollisionFxTemplate = (CEntityTemplate) LoadResource( 'sword_colision_fx' ); if( m_WeaponFXCollisionGroupNames.Size() == 0 ) { m_WeaponFXCollisionGroupNames.PushBack('Static'); m_WeaponFXCollisionGroupNames.PushBack('Foliage'); m_WeaponFXCollisionGroupNames.PushBack('Fence'); m_WeaponFXCollisionGroupNames.PushBack('BoatSide'); m_WeaponFXCollisionGroupNames.PushBack('Door'); m_WeaponFXCollisionGroupNames.PushBack('RigidBody'); m_WeaponFXCollisionGroupNames.PushBack('Dynamic'); m_WeaponFXCollisionGroupNames.PushBack('Destructible'); } if ( counterCollisionGroupNames.Size() == 0 ) { counterCollisionGroupNames.PushBack('Static'); counterCollisionGroupNames.PushBack('Foliage'); counterCollisionGroupNames.PushBack('Fence'); counterCollisionGroupNames.PushBack('Terrain'); counterCollisionGroupNames.PushBack('Door'); counterCollisionGroupNames.PushBack('RigidBody'); counterCollisionGroupNames.PushBack('Dynamic'); counterCollisionGroupNames.PushBack('Destructible'); } //ps4 pad backlight color ResetPadBacklightColor(); if( spawnData.restored ) { if (IsCurrentlyUsingItemL()) { if (inv.HasItemById( currentlyEquipedItemL )) { OnUseSelectedItem(); } else { HideUsableItem(true); } } if ( GetCurrentMeleeWeaponType() == PW_Steel || GetCurrentMeleeWeaponType() == PW_Silver ) { OnEquipMeleeWeapon(GetCurrentMeleeWeaponType(), true, true); } AddTimer( 'UnmountCrossbowTimer', 0.01, true ); ClearBlockedSlots(); } ((CR4PlayerStateSwimming)this.GetState('Swimming')).OnParentSpawned(); //hack for possible immortality from finishers SetImmortalityMode( AIM_None, AIC_SyncedAnim ); //disable Dimeritium Bomb skill locks after load theGame.GetDefinitionsManager().GetContainedAbilities('DwimeritiumBomb_3', atts); for(i=0; i { skill = SkillNameToEnum(atts[i]); if(skill != S_SUndefined) BlockSkill(skill, false); } // phantom weapon manager this.GetInventory().GetItemEquippedOnSlot( EES_SteelSword, item ); if( this.GetInventory().ItemHasTag( item, 'PhantomWeapon' ) ) { this.InitPhantomWeaponMgr(); } //retoractive fix if(FactsQuerySum("mq3036_fact_done") > 0) BlockAllActions('mq3036', false); spawnedTime = theGame.GetEngineTimeAsSeconds(); if ( theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'EnableUberMovement' ) == "1" ) theGame.EnableUberMovement( true ); else theGame.EnableUberMovement( false ); // Initial level for Gwint Difficulty (Normal) if ( !FactsDoesExist("gwent_difficulty") ) FactsAdd("gwent_difficulty", 2); } public function GetTimeSinceSpawned() : float { return theGame.GetEngineTimeAsSeconds() - spawnedTime; } timer function UnmountCrossbowTimer( dt : float, id : int ) { var itemId : SItemUniqueId; itemId = this.inv.GetItemFromSlot( 'l_weapon' ); if ( inv.IsIdValid( itemId ) && inv.IsItemCrossbow( itemId ) ) { rangedWeapon = (Crossbow)( inv.GetItemEntityUnsafe( itemId ) ); if (rangedWeapon) { rangedWeapon.Initialize( (CActor)( rangedWeapon.GetParentEntity() ) ); OnRangedForceHolster( true, true ); RemoveTimer( 'UnmountCrossbowTimer' ); } } else RemoveTimer( 'UnmountCrossbowTimer' ); } event OnDestroyed() { playerAiming.RemoveAimingSloMo(); if(rangedWeapon) rangedWeapon.ClearDeployedEntity(true); ResetPadBacklightColor(); //remove combat mode no-save lock theGame.ReleaseNoSaveLock( noSaveLock ); } ///////////////////////////////////////////////////////////////////// ////////////////////////Radial Menu////////////////////////////////// //////////////////////////////////////////////////////////////////// public function GetBlockedSlots () : array < SRadialSlotDef > { return blockedRadialSlots; } public function ClearBlockedSlots() { var i : int; //var blockedSigns : array; //var playerWitcher : W3PlayerWitcher; for ( i = 0; i < blockedRadialSlots.Size(); i+=1 ) { if( !IsSwimming() ) { if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'swimming')) { i-=1; continue; } } if (!IsUsingVehicle()) { if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'useVehicle')) { i-=1; continue; } } if ( !IsCurrentlyUsingItemL() || !IsUsableItemLBlocked() ) { if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'usableItemL')) { i-=1; continue; } } if ( !IsThrowingItem() ) { if ( EnableRadialSlot(blockedRadialSlots[i].slotName, 'throwBomb')) { i-=1; continue; } } } // this is a hack that had to be added because someone ignored existing functionality of blocking radial slots propely and created BlockSignSelection. Unfortunately to keep the backwawrd compatibility I had to hack it. /*playerWitcher = (W3PlayerWitcher)this; if ( playerWitcher ) { blockedSigns = playerWitcher.GetBlockedSigns(); i = 0; for ( i = 0; i < blockedSigns.Size(); i+=1 ) { switch( blockedSigns[i] ) { case ST_Aard : if ( !IsRadialSlotBlocked ( 'Aard') ) { playerWitcher.BlockSignSelection(ST_Aard, false); } break; case ST_Axii : if ( !IsRadialSlotBlocked ( 'Axii') ) { playerWitcher.BlockSignSelection(ST_Axii, false ); } break; case ST_Igni : if ( !IsRadialSlotBlocked ( 'Igni') ) { playerWitcher.BlockSignSelection(ST_Igni, false ); } break; case ST_Quen : if ( !IsRadialSlotBlocked ( 'Quen') ) { playerWitcher.BlockSignSelection(ST_Quen, false ); } break; case ST_Yrden : if ( !IsRadialSlotBlocked ( 'Yrden') ) { playerWitcher.BlockSignSelection(ST_Yrden, false ); } break; default: break; } } }*/ } public function RestoreBlockedSlots () { var i : int; var slotsToBlock : array; for ( i = 0; i < blockedRadialSlots.Size(); i+=1 ) { slotsToBlock.PushBack ( blockedRadialSlots[i].slotName ); } if ( slotsToBlock.Size() > 0 ) { EnableRadialSlots ( false, slotsToBlock ); } } private function DisableRadialSlot ( slotName : name, sourceName : name ) : bool { var i : int; var k : int; var slotsToBlock : array; var blockedRadialSlotEntry : SRadialSlotDef; slotsToBlock.PushBack ( slotName ); for ( i = 0; i < blockedRadialSlots.Size(); i+=1 ) { if ( blockedRadialSlots[i].slotName == slotName ) { if ( sourceName != '' ) { for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 ) { if ( blockedRadialSlots[i].disabledBySources[k] == sourceName ) { return false; } } blockedRadialSlots[i].disabledBySources.PushBack ( sourceName ); return false; } return false; } } blockedRadialSlotEntry = InitBlockedRadialSlotEntry ( slotName ); if ( sourceName != '' ) { blockedRadialSlotEntry.disabledBySources.PushBack ( sourceName ); } blockedRadialSlots.PushBack ( blockedRadialSlotEntry ); EnableRadialSlots ( false, slotsToBlock ); return true; } public function EnableRadialSlot ( slotName : name, sourceName : name ) : bool { var i : int; var k : int; var slotsToBlock : array; slotsToBlock.PushBack ( slotName ); for ( i = 0; i < blockedRadialSlots.Size(); i+=1 ) { if ( blockedRadialSlots[i].slotName == slotName ) { if ( sourceName != '' ) { for ( k = 0; k < blockedRadialSlots[i].disabledBySources.Size(); k += 1 ) { if ( blockedRadialSlots[i].disabledBySources[k] == sourceName ) { blockedRadialSlots[i].disabledBySources.Remove ( blockedRadialSlots[i].disabledBySources[k] ); } } } if ( blockedRadialSlots[i].disabledBySources.Size() <= 0 ) { blockedRadialSlots.Remove( blockedRadialSlots[i] ); EnableRadialSlots ( true, slotsToBlock ); return true; } return false; } } return false; } private function InitBlockedRadialSlotEntry ( slotName : name ) : SRadialSlotDef { var blockedRadialSlotEntry : SRadialSlotDef; blockedRadialSlotEntry.slotName = slotName; return blockedRadialSlotEntry; } public function EnableRadialSlotsWithSource ( enable : bool, slotsToBlock : array < name >, sourceName : name ) { var i : int; for ( i = 0; i < slotsToBlock.Size(); i+=1 ) { if ( enable ) { EnableRadialSlot ( slotsToBlock[i], sourceName ); } else { DisableRadialSlot ( slotsToBlock[i], sourceName ); } } if ( blockedRadialSlots.Size() <= 0 ) { blockedRadialSlots.Clear(); } } public function IsRadialSlotBlocked ( slotName : name ) : bool { var i : int; for ( i = 0; i < blockedRadialSlots.Size(); i+=1 ) { if ( blockedRadialSlots[i].slotName == slotName ) { return true; } } return false; } ///////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /////////////////////// @Reapir Kits //////////////////////////////////// //////////////////////////////////////////////////////////////////// public function RepairItem ( rapairKitId : SItemUniqueId, usedOnItem : SItemUniqueId ); public function HasRepairAbleGearEquiped () : bool; public function HasRepairAbleWaponEquiped () : bool; public function IsItemRepairAble ( item : SItemUniqueId ) : bool; ///////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /////////////////////// @OILS //////////////////////////////////// //////////////////////////////////////////////////////////////////// public function ApplyOil( oilId : SItemUniqueId, usedOnItem : SItemUniqueId ); public function IsEquippedSwordUpgradedWithOil(steel : bool, optional oilName : name) : bool; public function GetOilAppliedOnSword(steel : bool) : name; public function CanApplyOilOnItem(oilId : SItemUniqueId, usedOnItem : SItemUniqueId) : bool { if(inv.ItemHasTag(oilId, theGame.params.TAG_STEEL_OIL) && inv.IsItemSteelSwordUsableByPlayer(usedOnItem)) return true; if(inv.ItemHasTag(oilId, theGame.params.TAG_SILVER_OIL) && inv.IsItemSilverSwordUsableByPlayer(usedOnItem)) return true; return false; } //////////////////////////////////////////////////////////////////// public final function DidFailFundamentalsFirstAchievementCondition() : bool { return failedFundamentalsFirstAchievementCondition; } public final function SetFailedFundamentalsFirstAchievementCondition(b : bool) { var i : int; var npc : CNewNPC; failedFundamentalsFirstAchievementCondition = b; //save info in enemy since we might run away from combat and return, triggering new combat encounter if(failedFundamentalsFirstAchievementCondition) { for(i=0; i { if(hostileEnemies[i].HasTag(theGame.params.MONSTER_HUNT_ACTOR_TAG)) { npc = (CNewNPC)hostileEnemies[i]; npc.AddTag('failedFundamentalsAchievement'); npc.AddTimer('FundamentalsAchFailTimer', 30*60, , , , true, true); } } } } public function IsInCombatFist() : bool { return this.GetCurrentStateName() == 'CombatFists'; } public function IsInitialized() : bool; public function IsCiri() : bool { return ((W3ReplacerCiri)this); } protected function WouldLikeToMove() : bool { var speedVec : Vector; var speed, speedMult : float; // Get speed from input speedVec.X = theInput.GetActionValue( 'GI_AxisLeftX' ); //player.mainInput.aLeftJoyX; speedVec.Y = theInput.GetActionValue( 'GI_AxisLeftY' );//player.mainInput.aLeftJoyY; speed = VecLength2D( speedVec ); return speed > 0.1f; } function HandleMovement( deltaTime : float ) { // just to see if player would like to move if there would be possibility // example of use: movement is blocked when in critical state, but it can end earlier only if it would be desired by player // and this is nothing but desire to move // note: for some reason, when doing WouldLikeToMove()? 1.0f : 0.0f it just doesn't care and gives 0.0f if (WouldLikeToMove()) SetBehaviorVariable( 'playerWouldLikeToMove', 1.0f); else SetBehaviorVariable( 'playerWouldLikeToMove', 0.0f); super.HandleMovement( deltaTime ); } function BattleCryIsReady( ) : bool { var l_currentTime : float; l_currentTime = theGame.GetEngineTimeAsSeconds(); if( l_currentTime >= battlecry_timeForNext ) { return true; } return false; } function PlayBattleCry( _BattleCry : name , _Chance : float, optional _IgnoreDelay, ignoreRepeatCheck : bool ) { var l_randValue : float; var fact : int; fact = FactsQuerySum("force_stance_normal"); if( IsSwimming() || theGame.IsDialogOrCutscenePlaying() || IsInNonGameplayCutscene() || IsInGameplayScene() || theGame.IsCurrentlyPlayingNonGameplayScene() || theGame.IsFading() || theGame.IsBlackscreen() || FactsQuerySum("force_stance_normal") > 0 ) { return; } // To avoid calling too often the same type of battle cry if ( !ignoreRepeatCheck ) { if( battlecry_lastTry == _BattleCry ) return; } battlecry_lastTry = _BattleCry; l_randValue = RandF(); // Either use delay or chance if( l_randValue < _Chance && ( _IgnoreDelay || BattleCryIsReady() ) ) { thePlayer.PlayVoiceset( 90, _BattleCry ); // Restart counter battlecry_timeForNext = theGame.GetEngineTimeAsSeconds() + RandRangeF( battlecry_delayMax, battlecry_delayMin ); } } public final function OnWeatherChanged() { if( IsInInterior() || GetCurrentStateName() != 'Exploration' || theGame.IsDialogOrCutscenePlaying() || IsInNonGameplayCutscene() || IsInGameplayScene() || theGame.IsCurrentlyPlayingNonGameplayScene() || theGame.IsFading() || theGame.IsBlackscreen() || GetTimeSinceSpawned() < 60 ) { return; } AddTimer( 'CommentOnWeather', 1 ); } public final timer function CommentOnWeather( _Delta : float, _Id : int ) { var l_weather : name; var l_currentArea : EAreaName; var l_rand : float; l_weather = GetWeatherConditionName(); l_currentArea = theGame.GetCommonMapManager().GetCurrentArea(); switch ( l_weather ) { case 'WT_Clear': l_rand = RandF(); if( l_rand > 0.66f && !AreaIsCold() && theGame.envMgr.IsDay() ) { thePlayer.PlayVoiceset( 90, 'WeatherHot' ); } else if ( l_rand > 0.33f ) { thePlayer.PlayVoiceset( 90, 'WeatherClearingUp' ); } break; case 'WT_Rain_Storm': thePlayer.PlayVoiceset( 90, 'WeatherStormy' ); break; case 'WT_Light_Clouds': if( previousRainStrength < GetRainStrength() ) { thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' ); } else if( AreaIsCold() && previousWeather == 'WT_Clear' ) { thePlayer.PlayVoiceset( 90, 'WeatherCold' ); } break; case 'WT_Mid_Clouds': if( previousRainStrength < GetRainStrength() ) { thePlayer.PlayVoiceset( 90, 'WeatherRaining' ); } else if( AreaIsCold() && previousWeather == 'WT_Clear' ) { thePlayer.PlayVoiceset( 90, 'WeatherCold' ); } break; case 'WT_Mid_Clouds_Dark': if( previousWeather != 'WT_Heavy_Clouds' && previousWeather != 'WT_Heavy_Clouds_Dark' ) thePlayer.PlayVoiceset( 90, 'WeatherWindy' ); break; case 'WT_Heavy_Clouds': if( previousWeather != 'WT_Mid_Clouds_Dark' && previousWeather != 'WT_Heavy_Clouds_Dark' ) thePlayer.PlayVoiceset( 90, 'WeatherWindy' ); break; case 'WT_Heavy_Clouds_Dark': if( thePlayer.IsOnBoat() ) { thePlayer.PlayVoiceset( 90, 'WeatherSeaWillStorm' ); } else if( previousRainStrength < GetRainStrength() ) { thePlayer.PlayVoiceset( 90, 'WeatherLooksLikeRain' ); } else { thePlayer.PlayVoiceset( 90, 'WeatherWindy' ); } break; case 'WT_Snow': if( RandF() > 0.5f ) thePlayer.PlayVoiceset( 90, 'WeatherSnowy' ); else thePlayer.PlayVoiceset( 90, 'WeatherCold' ); break; } previousRainStrength = GetRainStrength(); previousWeather = l_weather; } function CanUpdateMovement() : bool { if ( rangedWeapon && GetBehaviorVariable( 'fullBodyAnimWeight' ) >= 1.f && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) return false; return true; } public function SetDefaultLocomotionController() { if( !defaultLocomotionController ) { defaultLocomotionController = new CR4LocomotionPlayerControllerScript in this; } ActionDirectControl( defaultLocomotionController ); } event OnPlayerTickTimer( deltaTime : float ) { var focusModeController : CFocusModeController; var cnt : int; super.OnPlayerTickTimer( deltaTime ); HandleMovement( deltaTime ); if ( playerAiming.GetCurrentStateName() == 'Aiming' ) { FindTarget(); FindNonActorTarget( false ); UpdateDisplayTarget(); UpdateLookAtTarget(); } else { if( playerTickTimerPhase == 0 ) { FindTarget(); } else if( playerTickTimerPhase == 1 ) { FindNonActorTarget( false ); } else if ( playerTickTimerPhase == 2 ) { UpdateDisplayTarget(); UpdateLookAtTarget(); } } //CombatModeDebug(); playerTickTimerPhase = ( playerTickTimerPhase + 1 ) % 3; focusModeController = theGame.GetFocusModeController(); focusModeController.UpdateFocusInteractions( deltaTime ); //some behavior hack for critical states, moved from effectsManager.PerformUpdate() since it does not tick continuously anymore cnt = (int)( effectManager.GetCriticalBuffsCount() > 0 ); SetBehaviorVariable('hasCriticalBuff', cnt); } event OnDeath( damageAction : W3DamageAction ) { super.OnDeath( damageAction ); RemoveTimer('RequestCriticalAnimStart'); //theInput.SetContext('Death'); EnableFindTarget( false ); BlockAllActions('Death', true); EnableHardLock( false ); theGame.CreateNoSaveLock( 'player_death', deathNoSaveLock, false, false ); theGame.SetDeathSaveLockId( deathNoSaveLock ); ClearHostileEnemiesList(); RemoveReactions(); SetPlayerCombatTarget(NULL); OnEnableAimingMode( false ); } // Called when the actor gets out of unconscious state function OnRevived() { super.OnRevived(); BlockAllActions('Death', false); theGame.ReleaseNoSaveLock(deathNoSaveLock); this.RestartReactionsIfNeeded(); } public function CanStartTalk() : bool { if ( beingWarnedBy.Size() > 0 ) return false; return super.CanStartTalk(); } /////////////////////////////////////////////////////////////////////////// // @Counters /////////////////////////////////////////////////////////////////////////// //caches timestamp of counter use (button press) public function AddCounterTimeStamp(time : EngineTime) {counterTimestamps.PushBack(time);} /* This function checks if we have performed a counter It checks timestamps of moments when we pressed the parry/counter button in order to determine if the player was spamming the button. If so then this is not a counter. Returns true if the counter is valid */ public function CheckCounterSpamming(attacker : CActor) : bool { var counterWindowStartTime : EngineTime; //the time when the counter window (in anim) started var i, spamCounter : int; var reflexAction : bool; var testEngineTime : EngineTime; if(!attacker) return false; counterWindowStartTime = ((CNewNPC)attacker).GetCounterWindowStartTime(); spamCounter = 0; reflexAction = false; //if counterWindowStartTime was never set return false - PF if ( counterWindowStartTime == testEngineTime ) { return false; } for(i = counterTimestamps.Size() - 1; i>=0; i-=1) { //log number of button presses since 0.4 seconds before the counter timewindow if(counterTimestamps[i] >= (counterWindowStartTime - EngineTimeFromFloat(0.4)) ) { //spamCounter += 1; Original Code - Legendary Counter modded this line spamCounter = 1; } //and at the same time remove all outdated data on the fly else { counterTimestamps.Remove(counterTimestamps[i]); continue; } //set info that we have a potential parry if this press was after the counter timewindow started if(!reflexAction && (counterTimestamps[i] >= counterWindowStartTime)) reflexAction = true; } /* If reflexAction is set then we have at least 1 button press within the counter timewindow. //if(spamCounter == 1 && reflexAction) Original Code - Legendary Counter modded this line if(spamCounter == 1 || reflexAction) 1 means exactly one button press - a potential counter (if reflexAction is set as well) >1 means spamming */ if(spamCounter == 1 && reflexAction) return true; return false; } protected function PerformCounterCheck(parryInfo: SParryInfo) : bool { var mult : float; var parryType : EParryType; var validCounter, useKnockdown : bool; var slideDistance, duration : float; var playerToTargetRot : EulerAngles; var zDifference : float; var effectType : EEffectType; var repelType : EPlayerRepelType = PRT_Random; var params : SCustomEffectParams; var thisPos, attackerPos : Vector; var fistFightCheck : bool; var fistFightCounter : bool; var attackerInventory : CInventoryComponent; var weaponId : SItemUniqueId; var weaponTags : array; var playerToAttackerVector : Vector; var tracePosStart : Vector; var tracePosEnd : Vector; var hitPos : Vector; var hitNormal : Vector; if(ShouldProcessTutorial('TutorialDodge') || ShouldProcessTutorial('TutorialCounter')) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) ); FactsRemove("tut_fight_slomo_ON"); } if ( !parryInfo.canBeParried || parryInfo.attacker.HasAbility( 'CannotBeCountered' ) ) return false; fistFightCheck = FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightCounter ); if( ParryCounterCheck() && parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE && fistFightCheck ) { //check if this is a valid counter validCounter = CheckCounterSpamming(parryInfo.attacker); if(validCounter) { if ( IsInCombatActionFriendly() ) RaiseEvent('CombatActionFriendlyEnd'); SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) ); SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry //PPPP counter success sound //SoundEvent("global_machines_lift_wood1_mechanism_stop" ); SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) ); SetBehaviorVariable( 'counter', (float)validCounter); //1/true when the parry is a counter/reflex_parry this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry ); if ( !fistFightCounter ) { attackerInventory = parryInfo.attacker.GetInventory(); weaponId = attackerInventory.GetItemFromSlot('r_weapon'); attackerInventory.GetItemTags( weaponId , weaponTags ); /*if( parryInfo.attacker.HasTag( 'olgierd_gpl' ) && parryInfo.attackActionName == 'attack_heavy' ) { //DealCounterDamageToOlgierd(); GetTarget().AddAbility( 'HitCounterEnabled', false ); GetTarget().AddTimer( 'DisableHitCounterAfter', 3.0 ); }*/ //don't look at me like that. It is NOT a hack... follow the white rabbit... if ( parryInfo.attacker.HasAbility('mon_gravehag') ) { repelType = PRT_Slash; parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, 'ReflexParryPerformed'); //parryInfo.attacker.RemoveAbility('TongueAttack'); } else if ( (CNewNPC)parryInfo.attacker && !((CNewNPC)parryInfo.attacker).IsHuman() ) { repelType = PRT_SideStepSlash; } else if ( weaponTags.Contains('spear2h') ) { repelType = PRT_SideStepSlash; parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed"); parryInfo.attacker.SignalGameplayEvent( 'SpearDestruction'); } else { //-----pitch check------ thisPos = this.GetWorldPosition(); attackerPos = parryInfo.attacker.GetWorldPosition(); playerToTargetRot = VecToRotation( thisPos - attackerPos ); zDifference = thisPos.Z - attackerPos.Z; if ( playerToTargetRot.Pitch < -5.f && zDifference > 0.35 ) { repelType = PRT_Kick; //Pass attacker to the timer so that he ragdolls after a delay ragdollTarget = parryInfo.attacker; AddTimer( 'ApplyCounterRagdollTimer', 0.3 ); } else { useKnockdown = false; if ( CanUseSkill(S_Sword_s11) ) { if( GetSkillLevel(S_Sword_s11) > 1 && RandF() < GetWitcherPlayer().GetStat(BCS_Focus) )//CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'chance', false, true)) ) { duration = CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s11, 'duration', false, true)); useKnockdown = true; } } else if ( parryInfo.attacker.IsHuman() ) { //Apply knockdown if npc is countered on ledge tracePosStart = parryInfo.attacker.GetWorldPosition(); tracePosStart.Z += 1.f; playerToAttackerVector = VecNormalize( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() ); tracePosEnd = ( playerToAttackerVector * 0.75f ) + ( playerToAttackerVector * parryInfo.attacker.GetRadius() ) + parryInfo.attacker.GetWorldPosition(); tracePosEnd.Z += 1.f; if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) ) { tracePosStart = tracePosEnd; tracePosEnd -= 3.f; if ( !theGame.GetWorld().StaticTrace( tracePosStart, tracePosEnd, hitPos, hitNormal, counterCollisionGroupNames ) ) useKnockdown = true; } } if(useKnockdown && (!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown) || !parryInfo.attacker.IsImmuneToBuff(EET_Knockdown))) { if(!parryInfo.attacker.IsImmuneToBuff(EET_HeavyKnockdown)) { params.effectType = EET_HeavyKnockdown; } else { params.effectType = EET_Knockdown; } repelType = PRT_Kick; params.creator = this; params.sourceName = "ReflexParryPerformed"; params.duration = duration; parryInfo.attacker.AddEffectCustom(params); } else { parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed"); } } } parryInfo.attacker.GetInventory().PlayItemEffect(parryInfo.attackerWeaponId, 'counterattack'); //by default repelType is PRT_Random if ( repelType == PRT_Random ) if ( RandRange(100) > 50 ) repelType = PRT_Bash; else repelType = PRT_Kick; this.SetBehaviorVariable( 'repelType', (int)repelType ); parryInfo.attacker.SetBehaviorVariable( 'repelType', (int)repelType ); } else { parryInfo.attacker.AddEffectDefault(EET_CounterStrikeHit, this, "ReflexParryPerformed"); } //SetCustomOrientationTargetForCombatActions( OT_None ); SetParryTarget ( parryInfo.attacker ); SetSlideTarget( parryInfo.attacker ); if ( !IsActorLockedToTarget() ) SetMoveTarget( parryInfo.attacker ); if ( RaiseForceEvent( 'PerformCounter' ) ) OnCombatActionStart(); SetCustomRotation( 'Counter', VecHeading( parryInfo.attacker.GetWorldPosition() - this.GetWorldPosition() ), 0.0f, 0.2f, false ); AddTimer( 'UpdateCounterRotation', 0.4f, true ); AddTimer( 'SetCounterRotation', 0.2f ); IncreaseUninterruptedHitsCount(); //counters also count as uninterrupted hits //drain stamina if(IsHeavyAttack(parryInfo.attackActionName)) mult = theGame.params.HEAVY_STRIKE_COST_MULTIPLIER; DrainStamina(ESAT_Counterattack, 0, 0, '', 0, mult); theGame.GetGamerProfile().IncStat(ES_CounterattackChain); } else { ResetUninterruptedHitsCount(); } return validCounter; } return false; } timer function UpdateCounterRotation( dt : float, id : int ) { UpdateCustomRotationHeading( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ) ); } timer function SetCounterRotation( dt : float, id : int ) { SetCustomRotation( 'Counter', VecHeading( parryTarget.GetWorldPosition() - this.GetWorldPosition() ), 360.f, 0.2f, false ); } private var parryTarget : CActor; private function SetParryTarget( t : CActor ) { parryTarget = t; } private var ragdollTarget : CActor; timer function ApplyCounterRagdollTimer( time : float , id : int) { var actor : CActor; actor = (CActor)ragdollTarget; if(actor) { actor.AddEffectDefault(EET_HeavyKnockdown, this, 'ReflexParryPerformed'); } } /////////////////////////////////////////////////////////////////////////// // Player Mode public function EnableMode( mode : EPlayerMode, enable : bool ) { playerMode.EnableMode( mode, enable ); } public function GetPlayerMode() : W3PlayerMode { return playerMode; } private function GetClosestIncomingAttacker() : CActor { var i, size : int; var attackerToPlayerDistances : array< float >; var closestAttackerIndex : int; var incomingAttackers : array; //incomingAttackers = this.combatManager.SendTicketOwners( CTT_Attack ); if(playerMode && playerMode.combatDataComponent) { if ( incomingAttackers.Size() <= 0 ) this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Charge' ); if ( incomingAttackers.Size() <= 0 ) this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Melee' ); if ( incomingAttackers.Size() <= 0 ) this.playerMode.combatDataComponent.GetTicketSourceOwners( incomingAttackers, 'TICKET_Range' ); } size = incomingAttackers.Size(); attackerToPlayerDistances.Resize( size ); if ( size > 0 ) { for ( i = incomingAttackers.Size()-1; i >= 0; i -= 1) { if ( !IsEnemyVisible( incomingAttackers[i] ) ) { incomingAttackers.EraseFast( i ); } } } if ( size > 0 ) { for ( i = 0; i < size; i += 1 ) { attackerToPlayerDistances[i] = VecDistance( incomingAttackers[i].GetWorldPosition(), this.GetWorldPosition() ); } closestAttackerIndex = ArrayFindMinF( attackerToPlayerDistances ); return incomingAttackers[ closestAttackerIndex ]; } else { return NULL; } } // Combat Timer timer function CombatCheck( time : float , id : int) { var i : int; var strLevel, temp : string; var enemies : array; UpdateFinishableEnemyList(); FindMoveTarget(); playerMode.UpdateCombatMode(); if( GetPlayerCombatStance() == PCS_Guarded ) { if( GetTarget().GetHealthPercents() > 0.25f ) { PlayBattleCry( 'BattleCryTaunt', 0.2f ); } else { if( GetTarget().IsHuman() ) PlayBattleCry( 'BattleCryHumansEnd', 0.3f ); else PlayBattleCry( 'BattleCryMonstersEnd', 0.3f ); } } if(IsThreatened() && ShouldProcessTutorial('TutorialMonsterThreatLevels') && FactsQuerySum("q001_nightmare_ended") > 0) { GetEnemiesInRange(enemies); for(i=0; i { strLevel = ((CNewNPC)enemies[i]).GetExperienceDifferenceLevelName(temp); if(strLevel == "deadlyLevel" || strLevel == "highLevel") { FactsAdd("tut_high_threat_monster"); break; } } } } public function ReceivedDamageInCombat() : bool { return receivedDamageInCombat; } //called when combat starts event OnCombatStart() { var weaponType : EPlayerWeapon; theGame.CreateNoSaveLock( 'combat', noSaveLock ); //cerberus achievement FactsRemove("statistics_cerberus_sign"); FactsRemove("statistics_cerberus_petard"); FactsRemove("statistics_cerberus_bolt"); FactsRemove("statistics_cerberus_fists"); FactsRemove("statistics_cerberus_melee"); FactsRemove("statistics_cerberus_environment"); BlockAction(EIAB_OpenMeditation, 'InCombat'); BlockAction(EIAB_HighlightObjective, 'InCombat'); if ( !this.IsUsingBoat() && GetTarget().GetAttitude(this) == AIA_Hostile ) { weaponType = GetMostConvenientMeleeWeapon( GetTarget() ); if ( weaponType == PW_Steel || weaponType == PW_Silver ) this.OnEquipMeleeWeapon( weaponType, false ); } } //called when combat finishes event OnCombatFinished() { var cnt : int; reevaluateCurrentWeapon = false; thePlayer.HardLockToTarget( false ); receivedDamageInCombat = false; //cerberus achievement cnt = 0; if(FactsQuerySum("statistics_cerberus_sign") > 0) cnt += 1; if(FactsQuerySum("statistics_cerberus_petard") > 0) cnt += 1; if(FactsQuerySum("statistics_cerberus_bolt") > 0) cnt += 1; if(FactsQuerySum("statistics_cerberus_fists") > 0) cnt += 1; if(FactsQuerySum("statistics_cerberus_melee") > 0) cnt += 1; if(FactsQuerySum("statistics_cerberus_environment") > 0) cnt += 1; //failsafe FactsRemove("statistics_cerberus_sign"); FactsRemove("statistics_cerberus_petard"); FactsRemove("statistics_cerberus_bolt"); FactsRemove("statistics_cerberus_fists"); FactsRemove("statistics_cerberus_melee"); FactsRemove("statistics_cerberus_environment"); if(cnt >= 3) theGame.GetGamerProfile().AddAchievement(EA_Cerberus); //end of cerberus if(theGame.GetTutorialSystem() && FactsQuerySum("TutorialShowSilver") > 0) { FactsAdd("tut_show_silver_sword", 1); FactsRemove("TutorialShowSilver"); } this.SetBehaviorVariable('isInCombatForOverlay',0.f); GoToExplorationIfNeeded(); theGame.ReleaseNoSaveLock( noSaveLock ); LogChannel( 'OnCombatFinished', "OnCombatFinished: ReleaseNoSaveLock" ); SetFailedFundamentalsFirstAchievementCondition(false); UnblockAction(EIAB_OpenMeditation, 'InCombat'); UnblockAction(EIAB_HighlightObjective, 'InCombat'); } event OnReactToBeingHit( damageAction : W3DamageAction ) { var weaponType : EPlayerWeapon; super.OnReactToBeingHit(damageAction); if ( IsInCombat() && damageAction.attacker && damageAction.attacker == GetTarget() && !( this.IsUsingVehicle() && this.IsOnBoat() ) ) { weaponType = GetMostConvenientMeleeWeapon( GetTarget() ); if ( weaponType != PW_Fists && weaponType != PW_None && weaponType != this.GetCurrentMeleeWeaponType() ) OnEquipMeleeWeapon( weaponType, false ); } } //called when player receives damage in combat(except for toxicity) public function ReceivedCombatDamage() { receivedDamageInCombat = true; } /////////////////////////////////////////////////////////////////////////// // @Uninterrupted hits /////////////////////////////////////////////////////////////////////////// timer function UninterruptedHitsResetOnIdle(dt : float, id : int) { ResetUninterruptedHitsCount(); } public function ResetUninterruptedHitsCount() { uninterruptedHitsCount = 0; LogUnitAtt("Uninterrupted attacks reset!!!!"); } public function IncreaseUninterruptedHitsCount() { uninterruptedHitsCount += 1; LogUnitAtt("Uninterrupted attacks count increased to " + uninterruptedHitsCount); if(uninterruptedHitsCount == 4) AddTimer('StartUninterruptedBlurr', 1, false); //idle turn off timer AddTimer('UninterruptedHitsResetOnIdle', 4.f, false); } timer function StartUninterruptedBlurr(dt : float, id : int) { var changed : bool; var movingAgent : CMovingPhysicalAgentComponent; var target : CActor; //check if the timer is to be turned off if(uninterruptedHitsCount < 4) { LogUnitAtt("Stopping camera effect"); thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect); uninterruptedHitsCurrentCameraEffect = ''; uninterruptedHitsCameraStarted = false; RemoveTimer('StartUninterruptedBlurr'); } else //still valid { target = GetTarget(); if( target ) { movingAgent = ( (CMovingPhysicalAgentComponent) (target.GetMovingAgentComponent()) ); } if(!uninterruptedHitsCameraStarted) { LogUnitAtt("Starting camera effect"); AddTimer('StartUninterruptedBlurr', 0.001, true); //need to update per tick if(movingAgent && movingAgent.GetCapsuleHeight() > 2) uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY; else uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY; thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect); uninterruptedHitsCameraStarted = true; } else { changed = false; if(movingAgent && movingAgent.GetCapsuleHeight() > 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY) changed = true; else if(!movingAgent || ( movingAgent.GetCapsuleHeight() <= 2 && uninterruptedHitsCurrentCameraEffect != theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY) ) changed = true; //if the target's height has changed then swap the camera effect if(changed) { //stop current effect thePlayer.StopEffect(uninterruptedHitsCurrentCameraEffect); //change mode if(uninterruptedHitsCurrentCameraEffect == theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY) uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_REGULAR_ENEMY; else uninterruptedHitsCurrentCameraEffect = theGame.params.UNINTERRUPTED_HITS_CAMERA_EFFECT_BIG_ENEMY; //turn new camera effect on thePlayer.PlayEffect(uninterruptedHitsCurrentCameraEffect); } } } } /////////////////////////////////////////////////////////////////////////// // Exploration Actions /////////////////////////////////////////////////////////////////////////// private var playerActionEventListeners : array; private var playerActionEventBlockingListeners : array; private function PlayerActionBlockGameplayActions( sourceName : name, lock : bool, isFromPlace : bool ) { if ( lock ) { thePlayer.BlockAction( EIAB_Signs, sourceName, false, false, isFromPlace ); thePlayer.BlockAction( EIAB_DrawWeapon, sourceName, false, false, isFromPlace ); thePlayer.BlockAction( EIAB_CallHorse, sourceName, false, false, isFromPlace ); thePlayer.BlockAction( EIAB_FastTravel, sourceName, false, false, isFromPlace ); thePlayer.BlockAction( EIAB_Fists, sourceName, false, false, isFromPlace ); thePlayer.BlockAction( EIAB_InteractionAction, sourceName, false, false, isFromPlace ); thePlayer.DisableCombatState(); } else { thePlayer.UnblockAction( EIAB_Signs, sourceName ); thePlayer.UnblockAction( EIAB_DrawWeapon, sourceName ); thePlayer.UnblockAction( EIAB_CallHorse, sourceName ); thePlayer.UnblockAction( EIAB_FastTravel, sourceName ); thePlayer.UnblockAction( EIAB_Fists, sourceName ); thePlayer.UnblockAction( EIAB_InteractionAction, sourceName ); } } public function GetPlayerActionEventListeners() : array { return playerActionEventListeners; } //Registers for event + blocks GameplayActions public function RegisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool ) { if ( !playerActionEventListeners.Contains( listener ) ) { playerActionEventListeners.PushBack( listener ); } if ( listener.ShouldBlockGameplayActionsOnInteraction() ) { if ( !playerActionEventBlockingListeners.Contains( listener ) ) { playerActionEventBlockingListeners.PushBack( listener ); } if ( playerActionEventBlockingListeners.Size() == 1 ) { PlayerActionBlockGameplayActions( 'PlayerAction', true, isLockedByPlace ); } } } //Unregisters for event + unblocks GameplayActions public function UnregisterForPlayerAction( listener : CGameplayEntity, isLockedByPlace : bool ) { playerActionEventListeners.Remove( listener ); playerActionEventBlockingListeners.Remove( listener ); if ( playerActionEventBlockingListeners.Size() == 0 ) { PlayerActionBlockGameplayActions( 'PlayerAction', false, isLockedByPlace ); } } event OnPlayerActionStart() { //MS: Only used for ProudWalk thePlayer.SetBehaviorVariable( 'inJumpState', 1.f ); } event OnPlayerActionEnd() { var i : int; for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 ) { playerActionEventListeners[i].OnPlayerActionEnd(); } currentCustomAction = PEA_None; //MS: Only used for ProudWalk thePlayer.SetBehaviorVariable( 'inJumpState', 0.f ); } event OnPlayerActionStartFinished() { var i : int; for ( i = playerActionEventListeners.Size() - 1; i >= 0; i-=1 ) { playerActionEventListeners[i].OnPlayerActionStartFinished(); } } function PlayerStartAction( playerAction : EPlayerExplorationAction, optional animName : name ) : bool { if ( playerAction == PEA_SlotAnimation && !IsNameValid(animName) ) { return false; } SetBehaviorVariable( 'playerStopAction', 0.0); SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction); /*if ( playerAction == PEA_SlotAnimation ) { if ( !this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',animName) ) return false; }*/ if ( RaiseForceEvent('playerActionStart') ) { currentCustomAction = playerAction; if ( playerAction == PEA_SlotAnimation ) { playerActionSlotAnimName = animName; AddTimer('PlayActionAnimWorkaround',0,false); } return true; } return false; } private var playerActionSlotAnimName : name; timer function PlayActionAnimWorkaround( dt : float , id : int) { this.ActionPlaySlotAnimationAsync('PLAYER_ACTION_SLOT',playerActionSlotAnimName, 0.2, 0.2, true); } function PlayerStopAction( playerAction : EPlayerExplorationAction ) { SetBehaviorVariable( 'playerExplorationAction', (float)(int)playerAction); SetBehaviorVariable( 'playerStopAction', 1.0); currentCustomAction = PEA_None; } function GetPlayerAction() : EPlayerExplorationAction { return currentCustomAction; } function MedallionPing() { var currTime : float = theGame.GetEngineTimeAsSeconds(); if ( lastMedallionEffect < currTime ) { lastMedallionEffect = theGame.GetEngineTimeAsSeconds() + medallion.effectDuration; medallion.TriggerMedallionFX(); } } /////////////////////////////////////////////////////////////////////////// // @INTERACTIONS /////////////////////////////////////////////////////////////////////////// public function CanPerformPlayerAction(optional alsoOutsideExplorationState : bool) : bool { //if in exploration or in any state and flag set if(!alsoOutsideExplorationState && GetCurrentStateName() != 'Exploration') return false; if( isInAir || (substateManager && !substateManager.CanInteract()) || IsInCombatAction() || GetCriticalBuffsCount() > 0) return false; return true; } //called when we receive an item event OnItemGiven(data : SItemChangedData) { var keyName : name; var i : int; var hud : CR4ScriptedHud; var message : string; var inve : CInventoryComponent; if(data.informGui) { hud = (CR4ScriptedHud)theGame.GetHud(); if(hud) { message = GetLocStringByKeyExt("panel_common_item_received") + ": " + GetLocStringByKeyExt(inv.GetItemLocalizedNameByUniqueID(data.ids[0])); if(data.quantity > 1) message += " x" + data.quantity; hud.HudConsoleMsg(message); } } inve = GetInventory(); //OnItemGiven can be called before we cache inventory component //key - check if we're next to a lock that uses this key and update interaction if needed if(inve.ItemHasTag(data.ids[0], 'key')) { keyName = inve.GetItemName(data.ids[0]); for(i=nearbyLockedContainersNoKey.Size()-1; i>=0; i-=1) { if(nearbyLockedContainersNoKey[i].GetKeyName() == keyName && nearbyLockedContainersNoKey[i].IsEnabled()) { nearbyLockedContainersNoKey[i].UpdateComponents("Unlock"); nearbyLockedContainersNoKey.Remove(nearbyLockedContainersNoKey[i]); } } } //alchemy level 3 items if(inve.IsItemAlchemyItem(data.ids[0])) { UpgradeAlchemyItem(data.ids[0], CanUseSkill(S_Perk_08)); } if(inve.ItemHasTag(data.ids[0], theGame.params.TAG_OFIR_SET)) CheckOfirSetAchievement(); } private final function CheckOfirSetAchievement() { var hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders : bool; //check player items CheckOfirItems(GetInventory(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders); //check stash items CheckOfirItems(GetWitcherPlayer().GetHorseManager().GetInventoryComponent(), hasArmor, hasBoots, hasGloves, hasPants, hasSword, hasSaddle, hasBag, hasBlinders); if(hasArmor && hasBoots && hasGloves && hasPants && hasSword && hasSaddle && hasBag && hasBlinders) theGame.GetGamerProfile().AddAchievement(EA_LatestFashion); } private final function CheckOfirItems(inv : CInventoryComponent, out hasArmor : bool, out hasBoots : bool, out hasGloves : bool, out hasPants : bool, out hasSword : bool, out hasSaddle : bool, out hasBag : bool, out hasBlinders : bool) { var ofirs : array; var i : int; ofirs = inv.GetItemsByTag(theGame.params.TAG_OFIR_SET); for(i=0; i { if(inv.IsItemChestArmor(ofirs[i])) { hasArmor = true; continue; } else if(inv.IsItemBoots(ofirs[i])) { hasBoots = true; continue; } else if(inv.IsItemGloves(ofirs[i])) { hasGloves = true; continue; } else if(inv.IsItemPants(ofirs[i])) { hasPants = true; continue; } else if(inv.IsItemSteelSwordUsableByPlayer(ofirs[i])) { hasSword = true; continue; } else if(inv.IsItemSilverSwordUsableByPlayer(ofirs[i])) { hasSword = true; continue; } else if(inv.IsItemSaddle(ofirs[i])) { hasSaddle = true; continue; } else if(inv.IsItemHorseBag(ofirs[i])) { hasBag = true; continue; } else if(inv.IsItemBlinders(ofirs[i])) { hasBlinders = true; continue; } } } //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading) public function ChangeAlchemyItemsAbilities(upgrade : bool) { var i : int; var dm : CDefinitionsManagerAccessor; var items : array; inv.GetAllItems(items); dm = theGame.GetDefinitionsManager(); for(i=0; i if(inv.IsItemAlchemyItem(items[i])) UpgradeAlchemyItem(items[i], upgrade); } //changes all alchemy items of level 3 abilities from level 2 to 3 (if upgrade) or from 3 to 2 (if not upgrading) public function UpgradeAlchemyItem(itemID : SItemUniqueId, upgrade : bool) { var j, currLevel, otherLevel : int; var dm : CDefinitionsManagerAccessor; var abs, currAbilities, otherAbilities : array; var min, max : SAbilityAttributeValue; if(!inv.IsItemAlchemyItem(itemID)) return; //get current level currLevel = (int)CalculateAttributeValue(inv.GetItemAttributeValue(itemID, 'level')); //if level ok then exit if(currLevel == 3 || currLevel == 2 || currLevel < 2 || currLevel > 3) return; //get current ability name currAbilities = inv.GetItemAbilitiesWithAttribute(itemID, 'level', currLevel); //get other ability name inv.GetItemContainedAbilities(itemID, abs); dm = theGame.GetDefinitionsManager(); for(j=0; j { dm.GetAbilityAttributeValue(abs[j], 'level', min, max); otherLevel = (int)CalculateAttributeValue(GetAttributeRandomizedValue(min, max)); if( (otherLevel == 2 || otherLevel == 3) && otherLevel != currLevel) otherAbilities.PushBack(abs[j]); } //swap abilities if(otherAbilities.Size() == 0) { LogAssert(false, "CR4Player.UpgradeAlchemyItem: cannot find ability to swap to from <<" + currAbilities[0] + ">> on item <<" + inv.GetItemName(itemID) + ">> !!!"); } else { for(j=0; j inv.RemoveItemBaseAbility(itemID, currAbilities[j]); for(j=0; j inv.AddItemBaseAbility(itemID, otherAbilities[j]); } } /////////////////////////////////////////////////////////////////////////// // Movement adjustment helper functions /////////////////////////////////////////////////////////////////////////// public function MovAdjRotateToTarget( ticket : SMovementAdjustmentRequestTicket ) { var movementAdjustor : CMovementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); var localOrientationTarget : EOrientationTarget = GetOrientationTarget(); if ( localOrientationTarget == OT_CustomHeading ) { movementAdjustor.RotateTo( ticket, GetOrientationTargetCustomHeading() ); } else if ( localOrientationTarget == OT_Actor ) { /*if ( parryTarget && IsGuarded() ) movementAdjustor.RotateTowards( ticket, parryTarget ); else*/ if ( slideTarget ) movementAdjustor.RotateTowards( ticket, slideTarget ); else if ( lAxisReleasedAfterCounter ) movementAdjustor.RotateTo( ticket, GetHeading() ); else movementAdjustor.RotateTo( ticket, GetCombatActionHeading() );//rawPlayerHeading ); } else if ( localOrientationTarget == OT_Player ) { if ( bLAxisReleased ) movementAdjustor.RotateTo( ticket, GetHeading() ); else movementAdjustor.RotateTo( ticket, rawPlayerHeading );//GetCombatActionHeading() ); } else if ( localOrientationTarget == OT_CameraOffset ) { //movementAdjustor.RotateTo( ticket, VecHeading( cachedCameraVector ) );//rawCameraHeading - oTCameraOffset ); movementAdjustor.RotateTo( ticket, VecHeading( theCamera.GetCameraDirection() ) );//rawCameraHeading ); } else { // default to camera movementAdjustor.RotateTo( ticket, rawCameraHeading ); } // never rotate to player } //////////////////////////////////////////////////////////////////////////////////// // Look at targets - moved here from movables //////////////////////////////////////////////////////////////////////////////////// //var cachedCameraVector : Vector; public function UpdateLookAtTarget() { var localOrientationTarget : EOrientationTarget; var playerRot : EulerAngles; var lookAtActive : Float; var lookAtTarget : Vector; var headBoneIdx : int; var tempComponent : CDrawableComponent; var entityHeight : float; var useTorsoBone : bool; var angles : EulerAngles; var dir : Vector; var camZ : float; var target : CActor; lookAtActive = 0.0f; localOrientationTarget = GetOrientationTarget(); if ( localOrientationTarget == OT_Player || localOrientationTarget == OT_CustomHeading ) { /*headBoneIdx = GetTorsoBoneIndex(); if ( headBoneIdx >= 0 ) { lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) ); }*/ //lookAtTarget = GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget; if ( localOrientationTarget == OT_Player ) angles = VecToRotation( GetHeadingVector() ); else if ( customOrientationInfoStack.Size() > 0 ) angles = VecToRotation( VecFromHeading( customOrientationInfoStack[ customOrientationInfoStack.Size() - 1 ].customHeading ) ); else angles = VecToRotation( GetHeadingVector() ); //angles.Pitch = oTCameraPitchOffset; dir = RotForward( angles ); lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget; lookAtTarget.Z += 1.6f; lookAtActive = 1.0f; } else if ( localOrientationTarget == OT_Camera ) { headBoneIdx = GetHeadBoneIndex(); if ( headBoneIdx >= 0 ) { lookAtTarget = MatrixGetTranslation( GetBoneWorldMatrixByIndex( headBoneIdx ) ); } else { lookAtTarget = GetWorldPosition(); lookAtTarget.Z += 1.6f; // fake head? } lookAtTarget += theCamera.GetCameraDirection() * 100.f; lookAtActive = 1.0f; } else if ( localOrientationTarget == OT_CameraOffset ) { /*lookAtTarget = GetWorldPosition(); lookAtTarget.Z += 1.6f; // fake head? camDir = theCamera.GetCameraDirection(); camZ = camDir.Z;// + 0.1; camDir = VecFromHeading( VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset ) * VecLength2D( camDir ); camDir.Z = camZ;*/ dir = theCamera.GetCameraDirection(); angles = VecToRotation( dir ); angles.Pitch = -angles.Pitch + oTCameraPitchOffset; angles.Yaw -= oTCameraOffset; dir = RotForward( angles ); lookAtTarget = dir * 30.f + this.GetWorldPosition();// + lookAtTarget; lookAtTarget.Z += 1.6f; lookAtActive = 1.0f; } else if ( localOrientationTarget == OT_Actor ) { if ( IsInCombatAction() ) { if ( ( ( ( W3PlayerWitcher )this ).GetCurrentlyCastSign() != ST_None && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_ItemThrow ) //|| GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Crossbow ) useTorsoBone = true; } if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) useTorsoBone = true; if ( tempLookAtTarget && (CActor)(tempLookAtTarget) ) { lookAtTarget = ProcessLookAtTargetPosition( tempLookAtTarget, useTorsoBone ); lookAtActive = 1.0f; } if ( GetDisplayTarget() && IsDisplayTargetTargetable() ) { lookAtTarget = ProcessLookAtTargetPosition( GetDisplayTarget(), useTorsoBone ); lookAtActive = 1.0f; } else { //FAIL SAFE in case the displayTarget disappears for some reason if ( slideTarget ) { lookAtTarget = ProcessLookAtTargetPosition( slideTarget, useTorsoBone ); } else { target = GetTarget(); if ( target ) { lookAtTarget = ProcessLookAtTargetPosition( target, useTorsoBone ); } } lookAtActive = 1.0f; } if ( !slideTarget && !IsUsingVehicle() ) { // TODO maybe just get axis from head? playerRot = GetWorldRotation(); lookAtTarget = GetWorldPosition() + VecFromHeading( playerRot.Yaw ) * 100.0f; lookAtActive = 0.0f; } if ( useTorsoBone ) lookAtTarget.Z += 0.2f; } //lookAtTarget = player.GetHeadingVector() * 30.f + this.GetWorldPosition();// + lookAtTarget; //lookAtActive = 1.0f; GetVisualDebug().AddSphere('lookAtTarget', 1.f, lookAtTarget, true, Color(255,0,0), 3.0f ); SetLookAtPosition( lookAtTarget ); UpdateLookAtVariables( lookAtActive, lookAtTarget ); } private function ProcessLookAtTargetPosition( ent : CGameplayEntity, useTorsoBone : bool ) : Vector { var boneIdx : int; var actor : CActor; var lookAtTarget : Vector; var tempComponent : CDrawableComponent; var box : Box; var entityHeight : float; var entityPos : Vector; var predictedPos : Vector; var z : float; var entMat : Matrix; actor = (CActor)(ent); entityPos = ent.GetWorldPosition(); lookAtTarget = entityPos; if ( actor ) { if ( useTorsoBone ) boneIdx = actor.GetTorsoBoneIndex(); else boneIdx = actor.GetHeadBoneIndex(); } else boneIdx = -1; if ( !( ent.aimVector.X == 0 && ent.aimVector.Y == 0 && ent.aimVector.Z == 0 ) ) { entMat = ent.GetLocalToWorld(); lookAtTarget = VecTransform( entMat, ent.aimVector ); } else if ( boneIdx >= 0 ) { lookAtTarget = MatrixGetTranslation( ent.GetBoneWorldMatrixByIndex( boneIdx ) ); } else { if ( actor ) lookAtTarget.Z += ( ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight() * 0.5 ); // fake head? else { tempComponent = (CDrawableComponent)( ent.GetComponentByClassName('CDrawableComponent') ); if ( tempComponent.GetObjectBoundingVolume( box ) ) { entityHeight = box.Max.Z - box.Min.Z; lookAtTarget = lookAtTarget + Vector(0,0,entityHeight/2); } } } z = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetCapsuleHeight(); if ( actor ) { if ( PredictLookAtTargetPosition( actor, lookAtTarget.Z - entityPos.Z, predictedPos ) ) lookAtTarget = predictedPos; } return lookAtTarget; } private function PredictLookAtTargetPosition( targetActor : CActor, zOffSet : float, out predictedPos : Vector ) : bool { var virtualPos : Vector; var i : int; var dist : float; var deltaTime : float; var projSpeed : float; var projSpeedInt : Vector; var projAngle : float; var e3Hack : bool; var currentTimeInCurve : float; e3Hack = false; if ( rangedWeapon && rangedWeapon.GetDeployedEntity() && ( rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) ) { projSpeed = rangedWeapon.GetDeployedEntity().projSpeed; virtualPos = targetActor.GetWorldPosition(); if ( e3Hack && targetActor.HasTag( 'e3_griffin' ) ) { for ( i = 0; i < 10; i += 1 ) { dist = VecDistance( rangedWeapon.GetDeployedEntity().GetWorldPosition(), virtualPos ); deltaTime = dist/projSpeed; virtualPos = targetActor.PredictWorldPosition( deltaTime ); } } else return false; virtualPos.Z += zOffSet; predictedPos = virtualPos; GetVisualDebug().AddSphere('CrossbowPredictedPos', 1.0f, virtualPos , true, Color(255,50,50), 5.0f ); return true; } return false; } public function SetLookAtPosition( vec : Vector ) { lookAtPosition = vec; } public function GetLookAtPosition() : Vector { return lookAtPosition; } //////////////////////////////////////////////////////////////////////////////////// // Scene //////////////////////////////////////////////////////////////////////////////////// event OnBlockingSceneEnded( optional output : CStorySceneOutput) { //hack for possible immortality from finishers SetImmortalityMode( AIM_None, AIC_SyncedAnim ); super.OnBlockingSceneEnded(output); } //////////////////////////////////////////////////////////////////////////////////// // New combat / exploration and weapon drawing //////////////////////////////////////////////////////////////////////////////////// function GetCurrentMeleeWeaponName() : name { return weaponHolster.GetCurrentMeleeWeaponName(); } public function GetCurrentMeleeWeaponType() : EPlayerWeapon { return weaponHolster.GetCurrentMeleeWeapon(); } public function OnMeleeForceHolster(ignoreActionLock : bool) { weaponHolster.HolsterWeapon(ignoreActionLock, true); } event OnForcedHolsterWeapon() { weaponHolster.OnForcedHolsterWeapon(); } event OnEquippedItem( category : name, slotName : name ) { var weaponType : EPlayerWeapon; if ( slotName == 'r_weapon' ) { switch ( category ) { case 'None' : weaponType = PW_None; break; case 'fist' : weaponType = PW_Fists; break; case 'steelsword' : weaponType = PW_Steel; break; case 'silversword' : weaponType = PW_Silver; break; default : return true; } weaponHolster.OnEquippedMeleeWeapon( weaponType ); } } private var isHoldingDeadlySword : bool; public function ProcessIsHoldingDeadlySword() { isHoldingDeadlySword = IsDeadlySwordHeld(); } public function IsHoldingDeadlySword() : bool { return isHoldingDeadlySword; } event OnHolsteredItem( category : name, slotName : name ) { var weaponType : EPlayerWeapon; if ( slotName == 'r_weapon' ) { weaponType = weaponHolster.GetCurrentMeleeWeapon(); switch ( category ) { case 'fist' : if ( weaponType == PW_Fists ) weaponHolster.OnEquippedMeleeWeapon( PW_None ); return true; case 'steelsword' : if ( weaponType == PW_Steel ) weaponHolster.OnEquippedMeleeWeapon( PW_None ); return true; case 'silversword' : if ( weaponType == PW_Silver ) weaponHolster.OnEquippedMeleeWeapon( PW_None ); return true; default : return true; } } } event OnEquipMeleeWeapon( weaponType : EPlayerWeapon, ignoreActionLock : bool, optional sheatheIfAlreadyEquipped : bool ) { RemoveTimer( 'DelayedSheathSword' ); weaponHolster.OnEquipMeleeWeapon( weaponType, ignoreActionLock, sheatheIfAlreadyEquipped ); /*// Check if we want to go to combat or exploration if( weaponHolster.GetCurrentMeleeWeapon() == PW_None ) { GoToExplorationIfNeeded( ); } else { GoToCombatIfNeeded( ); }*/ m_RefreshWeaponFXType = true; } event OnHolsterLeftHandItem() { weaponHolster.OnHolsterLeftHandItem(); } timer function DelayedSheathSword( dt: float, id : int ) { if ( !IsCombatMusicEnabled() ) { if ( IsInCombatAction() || !IsActionAllowed( EIAB_DrawWeapon ) ) { LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath pushed to buffer" ); PushCombatActionOnBuffer(EBAT_Sheathe_Sword,BS_Pressed); } else { LogChannel( 'OnCombatFinished', "DelayedSheathSword: Sheath successful" ); OnEquipMeleeWeapon( PW_None, false ); } } } protected function ShouldAutoSheathSwordInstantly() : bool { var enemies : array; var i : int; GetEnemiesInRange( enemies ); for ( i = 0; i < enemies.Size(); i += 1 ) { if ( IsThreat( enemies[i] ) && VecDistance( enemies[i].GetWorldPosition(), this.GetWorldPosition() ) <= findMoveTargetDist ) { return false; } } return true; } public function PrepareToAttack( optional target : CActor, optional action : EBufferActionType ) { var weaponType : EPlayerWeapon; if( IsInAir() || !GetBIsCombatActionAllowed() ) { return ; } if( !target ) { target = (CActor)displayTarget; } if( !target && IsCombatMusicEnabled() ) { target = moveTarget; } if( !target ) { if ( this.GetCurrentStateName() == 'Exploration' ) { SetCombatActionHeading( ProcessCombatActionHeading( action ) ); thePlayer.CanAttackWhenNotInCombat( action, false, target ); } } weaponHolster.TryToPrepareMeleeWeaponToAttack(); //if ( this.GetCurrentStateName() == 'Exploration' ) //PF - commenting this because Geralt won't switch to proper state when you sheathe sword while mashing attack { weaponType = GetCurrentMeleeWeaponType(); if ( weaponType == PW_None ) { // Get the weapon we have to use weaponType = GetMostConvenientMeleeWeapon( target ); } // Can't go to combat if we are in not a proper state if( !OnStateCanGoToCombat() ) { return; } GoToCombat( weaponType ); } } public function DisplayCannotAttackMessage( actor : CActor ) : bool { if ( actor && ( actor.GetMovingAgentComponent().GetName() == "child_base" || ((CNewNPC)actor).GetNPCType() == ENGT_Quest ) ) { DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target")); return true; } return false; } public function GetMostConvenientMeleeWeapon( targetToDrawAgainst : CActor, optional ignoreActionLock : bool ) : EPlayerWeapon { return weaponHolster.GetMostConvenientMeleeWeapon( targetToDrawAgainst, ignoreActionLock ); } private var reevaluateCurrentWeapon : bool; event OnTargetWeaponDrawn() { var weaponType : EPlayerWeapon = this.GetCurrentMeleeWeaponType(); if ( weaponType == PW_Fists ) reevaluateCurrentWeapon = true; } public function GoToCombatIfNeeded( optional enemy : CActor ) : bool { var weaponType : EPlayerWeapon; var target : CActor; if( !enemy && IsInCombat() ) { target = GetTarget(); if ( target ) enemy = target; else enemy = moveTarget; } // Should we fight if( !ShouldGoToCombat( enemy ) ) { return false; } weaponType = this.GetCurrentMeleeWeaponType(); if ( weaponType == PW_None || ( reevaluateCurrentWeapon && weaponType == PW_Fists ) || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) ) { // Get the weapon we have to use weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy ); reevaluateCurrentWeapon = false; } // Change the state+ GoToCombat( weaponType ); return true; } public function GoToCombatIfWanted( ) : bool { var weaponType : EPlayerWeapon; var target : CActor; var enemy : CActor; if( !IsInCombat() ) { return false; } target = GetTarget(); if ( target ) enemy = target; else enemy = moveTarget; weaponType = this.GetCurrentMeleeWeaponType(); if ( weaponType == PW_None || ( !IsInCombat() && weaponHolster.IsOnTheMiddleOfHolstering() ) ) { // Get the weapon we have to use weaponType = weaponHolster.GetMostConvenientMeleeWeapon( enemy ); } // Change the state+ GoToCombat( weaponType ); return true; } public function GoToExplorationIfNeeded() : bool { /* if( GetCurrentStateName() == 'Exploration' ) { return false; } */ if( ! IsInCombatState() ) { return false; } if( !ShouldGoToExploration() ) { return false; } // Change fists weapon to none weaponHolster.EndedCombat(); // Change the state GotoState( 'Exploration' ); return true; } event OnStateCanGoToCombat() { return false; } event OnStateCanUpdateExplorationSubstates() { return false; } private function ShouldGoToCombat( optional enemy : CActor ) : bool { // TODO If we don't have a specific enemy, let's just check if there are hostiles to fight if ( !enemy ) { //return isFightingHostiles; return false; } // Can't go to combat if we are in not a proper state if( !OnStateCanGoToCombat() ) { return false; } // See if we should be fighting this enemy /*if ( !IsEnemyVisible( enemy ) ) { return false; }*/ /*if ( !WasVisibleInScaledFrame( enemy, 1.f, 1.f ) ) { return false; }*/ if ( this.GetCurrentStateName() == 'AimThrow' ) { return false; } if ( this.GetCurrentStateName() == 'Swimming' ) { return false; } if ( this.GetCurrentStateName() == 'TraverseExploration' ) { return false; } // TODO: Reenable or find somethingbetter // Temporaryly disabled cause it does not work on some terrain /* if ( !theGame.GetWorld().NavigationLineTest( GetWorldPosition(), enemy.GetWorldPosition(), 0.4 ) ) { return false; } */ return true; } private function ShouldGoToExploration() : bool { if ( IsInCombat() )//moveTarget && IsThreat( moveTarget ) ) { return false; } /*if( IsGuarded() ) { return false; }*/ if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) { return false; } if( IsFistFightMinigameEnabled() ) { return false; } if( IsKnockedUnconscious() ) { return false; } if( IsInCombatAction() ) { return false; } if( GetCriticalBuffsCount() > 0 ) { return false; } return true; } private function GoToCombat( weaponType : EPlayerWeapon, optional initialAction : EInitialAction ) { // Set up and change state switch( weaponType ) { case PW_Silver: ((W3PlayerWitcherStateCombatSilver) GetState('CombatSilver')).SetupState( initialAction ); GoToStateIfNew( 'CombatSilver' ); break; case PW_Steel: ((W3PlayerWitcherStateCombatSteel) GetState('CombatSteel')).SetupState( initialAction ); GoToStateIfNew( 'CombatSteel' ); break; case PW_Fists: case PW_None: default : ((W3PlayerWitcherStateCombatFists) GetState('CombatFists')).SetupState( initialAction ); GoToStateIfNew( 'CombatFists' ); break; } } public function GoToStateIfNew( newState : name, optional keepStack : bool, optional forceEvents : bool ) { if( newState != GetCurrentStateName() ) { GotoState( newState, keepStack, forceEvents ); } } // So we can debug and control what is changing the state public function GotoState( newState : name, optional keepStack : bool, optional forceEvents : bool ) { /*if( newState == 'Exploration' ) { newState = newState; }*/ super.GotoState( newState, keepStack, forceEvents ); //PushState( newState ); } /* public function PushState( newState : name ) { if( newState == 'Exploration' ) { newState = newState; } super.PushState( newState ); } public function PopState( optional popAll : bool ) { super.PopState( popAll ); } */ public function IsThisACombatSuperState( stateName : name ) : bool { return stateName == 'Combat' || stateName == 'CombatSteel' || stateName == 'CombatSilver' || stateName == 'CombatFists'; } public function GetWeaponHolster() : WeaponHolster { return weaponHolster; } public function AbortSign() { var playerWitcher : W3PlayerWitcher; var sign : W3SignEntity; playerWitcher = (W3PlayerWitcher)this; if(playerWitcher) { sign = (W3SignEntity)playerWitcher.GetCurrentSignEntity(); if (sign) { sign.OnSignAborted(); } } } /////////////////////////////////////////////////////////////////////////// // Animation event handlers /////////////////////////////////////////////////////////////////////////// protected var disableActionBlend : bool; //KonradSuperDodgeHACK: To make dodge more responsive during NORMAL ATTACKS, dodge will fire immediately when hit animation can be played. //When hit anim is disabled, then the action will be cached and will be processed at the END of DisallowHitAnim event. //During all other actions, however, it will use the normal check of inputAllowed and combatActionAllowed. This is a super hack. And we will all go to hell for this. event OnAnimEvent_DisallowHitAnim( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( animEventType == AET_DurationEnd ) { if ( ( BufferCombatAction == EBAT_Dodge || BufferCombatAction == EBAT_Roll ) && IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) { //LogChannel('combatActionAllowed',"BufferCombatAction != EBAT_EMPTY"); ( (CR4Player)this ).ProcessCombatActionBuffer(); disableActionBlend = true; } } else if ( IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge && animEventType == AET_DurationStart ) { disableActionBlend = false; } super.OnAnimEvent_DisallowHitAnim( animEventName, animEventType, animInfo ); } event OnAnimEvent_FadeOut( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { theGame.FadeOutAsync( 0.2, Color( 0, 0, 0, 1 ) ); } event OnAnimEvent_FadeIn( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { theGame.FadeInAsync( 0.4 ); } event OnAnimEvent_BloodTrailForced( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { var bloodTrailParam : CBloodTrailEffect; var weaponId : SItemUniqueId; if ( isInFinisher ) { bloodTrailParam = (CBloodTrailEffect)(GetFinisherVictim()).GetGameplayEntityParam( 'CBloodTrailEffect' ); weaponId = this.inv.GetItemFromSlot('r_weapon'); if ( bloodTrailParam ) thePlayer.inv.PlayItemEffect( weaponId, bloodTrailParam.GetEffectName() ); } } event OnAnimEvent_SlowMo( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( isInFinisher && DisableManualCameraControlStackHasSource( 'Finisher' ) ) { if( animEventType != AET_DurationEnd ) theGame.SetTimeScale( 0.1f, 'AnimEventSlomoMo', 1000, true ); else theGame.RemoveTimeScale( 'AnimEventSlomoMo' ); } } event OnAnimEvent_PlayFinisherBlood( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( isInFinisher ) { SpawnFinisherBlood(); } } event OnAnimEvent_OnWeaponDrawReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { weaponHolster.OnWeaponDrawReady(); } event OnAnimEvent_OnWeaponHolsterReady( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { weaponHolster.OnWeaponHolsterReady(); } event OnAnimEvent_ThrowHoldTest( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { var thrownEntity : CThrowable; thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle ); if( IsThrowHold() ) { SetBehaviorVariable( 'throwStage', (int)TS_Loop ); PushState( 'AimThrow' ); thrownEntity.StartAiming(); } else { BombThrowRelease(); SetCombatIdleStance( 1.f ); } } event OnAnimEvent_AllowTempLookAt( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if( animEventType == AET_DurationStart ) SetTempLookAtTarget( slideTarget ); else if( animEventType == AET_DurationEnd ) SetTempLookAtTarget( NULL ); } protected var slideNPC : CNewNPC; protected var minSlideDistance : float; protected var slideTicket : SMovementAdjustmentRequestTicket; event OnAnimEvent_SlideToTarget( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { var movementAdjustor : CMovementAdjustor; if ( animEventType == AET_DurationStart ) slideNPC = (CNewNPC)slideTarget; if(!slideNPC) return false; if ( animEventType == AET_DurationStart && slideNPC.GetGameplayVisibility() ) { movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); slideTicket = movementAdjustor.GetRequest( 'SlideToTarget' ); movementAdjustor.CancelByName( 'SlideToTarget' ); slideTicket = movementAdjustor.CreateNewRequest( 'SlideToTarget' ); movementAdjustor.BindToEventAnimInfo( slideTicket, animInfo ); //movementAdjustor.Continuous(slideTicket); movementAdjustor.MaxLocationAdjustmentSpeed( slideTicket, 1000000 ); movementAdjustor.ScaleAnimation( slideTicket ); minSlideDistance = ((CMovingPhysicalAgentComponent)this.GetMovingAgentComponent()).GetCapsuleRadius()+((CMovingPhysicalAgentComponent)slideNPC.GetMovingAgentComponent()).GetCapsuleRadius(); movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, minSlideDistance ); } else if ( !slideNPC.GetGameplayVisibility() ) { movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); movementAdjustor.CancelByName( 'SlideToTarget' ); slideNPC = NULL; } else { movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); movementAdjustor.SlideTowards( slideTicket, slideTarget, minSlideDistance, minSlideDistance ); } } event OnAnimEvent_ActionBlend( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { } /* event OnAnimEvent_Throwable( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { var thrownEntity : CThrowable; thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle ); if ( inv.IsItemCrossbow( inv.GetItemFromSlot('l_weapon') ) && rangedWeapon.OnProcessThrowEvent( animEventName ) ) { return true; } else if( thrownEntity && IsThrowingItem() && thrownEntity.OnProcessThrowEvent( animEventName ) ) { return true; } }*/ event OnAnimEvent_SubstateManager( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { // Notify the exploration manager substateManager.OnAnimEvent( animEventName, animEventType, animInfo ); } event OnAnimEvent_AllowFall( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( !substateManager.m_OwnerMAC.IsOnGround() ) { substateManager.m_SharedDataO.SetFallFromCritical( true ); substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() ); substateManager.QueueStateExternal( 'Jump' ); RemoveBuff( EET_Knockdown, true ); RemoveBuff( EET_HeavyKnockdown, true ); return true; } return false; } event OnAnimEvent_AllowFall2( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( !substateManager.m_OwnerMAC.IsOnGround() ) { //substateManager.m_SharedDataO.m_FromCriticalB = true; //substateManager.m_MoverO.SetVelocity( -6.0f * GetWorldForward() ); substateManager.QueueStateExternal( 'Jump' ); RemoveBuff( EET_Knockdown, true ); RemoveBuff( EET_HeavyKnockdown, true ); } if( substateManager.StateWantsAndCanEnter( 'Slide' ) ) { substateManager.QueueStateExternal( 'Slide' ); } } event OnAnimEvent_DettachGround( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { //substateManager.m_MoverO.SetManualMovement( true ); } //pad vibration for finishers event OnAnimEvent_pad_vibration( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { var witcher : W3PlayerWitcher; theGame.VibrateControllerHard(); //delayed FX for runeword 10 & 12 witcher = GetWitcherPlayer(); if(isInFinisher && witcher) { if(HasAbility('Runeword 10 _Stats', true) && !witcher.runeword10TriggerredOnFinisher && ((bool)theGame.GetInGameConfigWrapper().GetVarValue('Gameplay', 'AutomaticFinishersEnabled')) == true) { witcher.Runeword10Triggerred(); witcher.runeword10TriggerredOnFinisher = true; } else if(HasAbility('Runeword 12 _Stats', true) && !witcher.runeword12TriggerredOnFinisher) { witcher.Runeword12Triggerred(); witcher.runeword12TriggerredOnFinisher = true; } } } //pad vibration light event OnAnimEvent_pad_vibration_light( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { //theGame.VibrateControllerLight(); //draw & sheathe weapon } event OnAnimEvent_KillWithRagdoll( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { //thePlayer.SetKinematic( false ); //thePlayer.Kill(); } event OnAnimEvent_RemoveBurning( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { thePlayer.AddBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning', true); } event OnAnimEvent_RemoveTangled( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( this.HasBuff( EET_Tangled ) ) { this.StopEffect('black_spider_web'); this.PlayEffectSingle('black_spider_web_break'); } } /////////////////////////////////////////////////////////////////////////// event OnBehaviorGraphNotification( notificationName : name, stateName : name ) { substateManager.OnBehaviorGraphNotification( notificationName, stateName ); if( notificationName == 'PlayerRunActivate' ) { isInRunAnimation = true; } else if( notificationName == 'PlayerRunDeactivate' ) { isInRunAnimation = false; } } event OnEnumAnimEvent( animEventName : name, variant : SEnumVariant, animEventType : EAnimationEventType, animEventDuration : float, animInfo : SAnimationEventAnimInfo ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; var rotationRate : ERotationRate; if ( animEventName == 'RotateToTarget' ) { /** * Rotate player to target */ rotationRate = GetRotationRateFromAnimEvent( variant.enumValue ); movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); if ( animEventType == AET_DurationStart || animEventType == AET_DurationStartInTheMiddle ) { // when it starts (also in the middle - it may mean that we switch between events) // create request if there isn't any and always setup rotation rate if (! movementAdjustor.IsRequestActive( movementAdjustor.GetRequest( 'RotateToTarget' ) ) ) { // start rotation adjustment ticket = movementAdjustor.CreateNewRequest( 'RotateToTarget' ); // use adjustment duration only when RR_0 is selected, otherwise use continuous to match desired rotation as fast as possible if ((int)rotationRate == 0) movementAdjustor.AdjustmentDuration( ticket, animEventDuration ); else { movementAdjustor.Continuous( ticket ); movementAdjustor.BindToEvent( ticket, 'RotateToTarget' ); } movementAdjustor.DontUseSourceAnimation( ticket ); // do not use source anim as it will use delta seconds from event movementAdjustor.ReplaceRotation( ticket ); } else { // get existing ticket to update rotation rate ticket = movementAdjustor.GetRequest( 'RotateToTarget' ); } MovAdjRotateToTarget( ticket ); // update rotationRate if ((int)rotationRate > 0) { movementAdjustor.MaxRotationAdjustmentSpeed( ticket, (float)((int)rotationRate) ); } } else if ( animEventType == AET_DurationEnd ) { // it will end if there's no event, but sometimes one event could end and be followed by another // and we want to have that continuity kept, that's why we won't end request manually } else { // continuous update (makes more sense when there is no target and we want to rotate towards camera) ticket = movementAdjustor.GetRequest( 'RotateToTarget' ); MovAdjRotateToTarget( ticket ); } } super.OnEnumAnimEvent(animEventName, variant, animEventType, animEventDuration, animInfo); } event OnTeleported() { if( substateManager ) { substateManager.OnTeleported(); } } /*public function CaptureSafePosition() { lastSafePosition = GetWorldPosition(); lastSafeRotation = GetWorldRotation(); safePositionStored = true; }*/ /////////////////////////////////////////////////////////////////////////// // FISTFIGHT /////////////////////////////////////////////////////////////////////////// event OnStartFistfightMinigame() { super.OnStartFistfightMinigame(); //Goto state CombatFist SetFistFightMinigameEnabled( true ); FistFightHealthChange( true ); thePlayer.GetPlayerMode().ForceCombatMode( FCMR_QuestFunction ); SetImmortalityMode(AIM_Unconscious, AIC_Fistfight); thePlayer.SetBehaviorVariable( 'playerWeaponLatent', (int)PW_Fists ); GotoCombatStateWithAction( IA_None ); ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( true ); EquipGeraltFistfightWeapon( true ); BlockAction( EIAB_RadialMenu, 'FistfightMinigame' ,,true); BlockAction( EIAB_Signs, 'FistfightMinigame' ,,true); BlockAction( EIAB_ThrowBomb, 'FistfightMinigame' ,,true); BlockAction( EIAB_UsableItem, 'FistfightMinigame' ,,true); BlockAction( EIAB_Crossbow, 'FistfightMinigame' ,,true); BlockAction( EIAB_DrawWeapon, 'FistfightMinigame' ,,true); BlockAction( EIAB_RunAndSprint, 'FistfightMinigame' ,,true); BlockAction( EIAB_SwordAttack, 'FistfightMinigame' ,,true); BlockAction( EIAB_CallHorse, 'FistfightMinigame' ,,true); BlockAction( EIAB_Roll, 'FistfightMinigame' ,,true); BlockAction( EIAB_Interactions, 'FistfightMinigame' ,,true); BlockAction( EIAB_Explorations, 'FistfightMinigame' ,,true); BlockAction( EIAB_OpenInventory, 'FistfightMinigame' ,,true); BlockAction( EIAB_QuickSlots, 'FistfightMinigame' ,,true); BlockAction( EIAB_OpenCharacterPanel, 'FistfightMinigame' ,,true); } event OnEndFistfightMinigame() { ((CMovingAgentComponent)this.GetMovingAgentComponent()).SnapToNavigableSpace( false ); FistFightHealthChange( false ); thePlayer.GetPlayerMode().ReleaseForceCombatMode( FCMR_QuestFunction ); EquipGeraltFistfightWeapon( false ); SetFistFightMinigameEnabled( false ); SetImmortalityMode(AIM_None, AIC_Fistfight); BlockAllActions('FistfightMinigame',false); super.OnEndFistfightMinigame(); } public function GetFistFightFinisher( out masterAnimName, slaveAnimIndex : name ) { var index : int; index = RandRange(1); switch ( index ) { case 0 : masterAnimName = 'man_fistfight_finisher_1_win'; slaveAnimIndex = 'man_fistfight_finisher_1_looser'; } } public function SetFistFightMinigameEnabled( flag : bool ) { fistFightMinigameEnabled = flag; } public function SetFistFightParams( toDeath : bool, endsWithBS : bool ) { isFFMinigameToTheDeath = toDeath; FFMinigameEndsithBS = endsWithBS; } public function IsFistFightMinigameEnabled() : bool { return fistFightMinigameEnabled; } public function IsFistFightMinigameToTheDeath() : bool { return isFFMinigameToTheDeath; } public function FistFightHealthChange( val : bool ) { if( val == true ) { GeraltMaxHealth = thePlayer.GetStatMax(BCS_Vitality); ClampGeraltMaxHealth( 2000 ); SetHealthPerc( 100 ); } else { ClampGeraltMaxHealth( GeraltMaxHealth ); SetHealthPerc( 100 ); } } function ClampGeraltMaxHealth( val : float ) { thePlayer.abilityManager.SetStatPointMax( BCS_Vitality, val ); } function EquipGeraltFistfightWeapon( val : bool ) { if ( val ) { fistsItems = thePlayer.GetInventory().AddAnItem( 'Geralt Fistfight Fists', 1, true, true ); thePlayer.GetInventory().MountItem( fistsItems[0] , true ); } else { thePlayer.GetInventory().DropItem( fistsItems[0], true ); } } /////////////////////////////////////////////////////////////////////////// // GWINT /////////////////////////////////////////////////////////////////////////// public function GetGwintAiDifficulty() : EGwintDifficultyMode { return gwintAiDifficulty; } public function SetGwintAiDifficulty( difficulty : EGwintDifficultyMode ) { gwintAiDifficulty = difficulty; } public function GetGwintAiAggression() : EGwintAggressionMode { return gwintAiAggression; } public function SetGwintAiAggression( aggression : EGwintAggressionMode ) { gwintAiAggression = aggression; } public function GetGwintMinigameState() : EMinigameState { return gwintMinigameState; } public function SetGwintMinigameState( minigameState : EMinigameState ) { gwintMinigameState = minigameState; } public function OnGwintGameRequested( deckName : name ) { var gwintManager:CR4GwintManager; gwintManager = theGame.GetGwintManager(); gwintMinigameState = EMS_None; gwintManager.SetEnemyDeckByName(deckName); if (gwintManager.GetHasDoneTutorial() || !theGame.GetTutorialSystem().AreMessagesEnabled()) { gwintManager.gameRequested = true; theGame.RequestMenu( 'DeckBuilder' ); } else { theGame.RequestMenu( 'GwintGame' ); } } private var gwintCardNumbersArray : array; public function InitGwintCardNumbersArray( arr : array ) { gwintCardNumbersArray.Clear(); gwintCardNumbersArray = arr; } public function GetCardNumbersArray() : array { return gwintCardNumbersArray; } /////////////////////////////////////////////////////////////////////////// // COMBAT CAMERA /////////////////////////////////////////////////////////////////////////// protected var customCameraStack : array; public function AddCustomCamToStack( customCameraParams : SCustomCameraParams ) : int { if( customCameraParams.useCustomCamera ) { if ( customCameraParams.cameraParams.enums[0].enumType != 'ECustomCameraType' ) { LogChannel( 'CustomCamera', "ERROR: Selected enum is not a custom camera!!!" ); return -1; } else { customCameraStack.PushBack( customCameraParams ); return ( customCameraStack.Size() - 1 ); } } return 0; } public function DisableCustomCamInStack( customCameraStackIndex : int ) { if ( customCameraStackIndex != -1 ) customCameraStack[customCameraStackIndex].useCustomCamera = false; else LogChannel( 'CustomCamera', "ERROR: Custom camera to disable does not exist!!!" ); } event OnInteriorStateChanged( inInterior : bool ) { interiorCamera = inInterior; } event OnModifyPlayerSpeed( flag : bool ) { modifyPlayerSpeed = flag; SetBehaviorVariable( 'modifyPlayerSpeed', (float)modifyPlayerSpeed ); } event OnGameCameraTick( out moveData : SCameraMovementData, dt : float ) { var targetRotation : EulerAngles; /*var dist : float; if( thePlayer.IsInCombat() ) { dist = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() ); thePlayer.GetVisualDebug().AddText( 'dbg', dist, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) ); }*/ if ( isStartingFistFightMinigame ) { moveData.pivotRotationValue = fistFightTeleportNode.GetWorldRotation(); isStartingFistFightMinigame = false; } // Specific substate if( substateManager.UpdateCameraIfNeeded( moveData, dt ) ) { return true; } // focusMode camera if ( theGame.IsFocusModeActive() ) { theGame.GetGameCamera().ChangePivotRotationController( 'Exploration' ); theGame.GetGameCamera().ChangePivotDistanceController( 'Default' ); theGame.GetGameCamera().ChangePivotPositionController( 'Default' ); // HACK moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController(); moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController(); moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController(); // END HACK moveData.pivotPositionController.SetDesiredPosition( thePlayer.GetWorldPosition() ); moveData.pivotRotationController.SetDesiredPitch( -10.0f ); moveData.pivotRotationController.maxPitch = 50.0; moveData.pivotDistanceController.SetDesiredDistance( 3.5f ); if ( !interiorCamera ) { moveData.pivotPositionController.offsetZ = 1.5f; DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5f, 2.0f, 0.3f ), 0.20f, dt ); } else { moveData.pivotPositionController.offsetZ = 1.3f; DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5f, 2.3f, 0.5f ), 0.3f, dt ); } return true; } // HACK: Target heading ( Made for ladder ) if( substateManager.m_SharedDataO.IsForceHeading( targetRotation ) ) { moveData.pivotRotationController.SetDesiredHeading( targetRotation.Yaw ); moveData.pivotRotationController.SetDesiredPitch( targetRotation.Pitch ); moveData.pivotRotationValue.Yaw = LerpAngleF( 2.1f * dt, moveData.pivotRotationValue.Yaw, targetRotation.Yaw ); moveData.pivotRotationValue.Pitch = LerpAngleF( 1.0f * dt, moveData.pivotRotationValue.Pitch, targetRotation.Pitch ); //return true; } if( customCameraStack.Size() > 0 ) { // HANDLE CUSTOM CAMERAS HERE // IF HANDLED - RETURN TRUE } return false; } private var questCameraRequest : SQuestCameraRequest; private var cameraRequestTimeStamp : float; public function RequestQuestCamera( camera : SQuestCameraRequest ) { questCameraRequest = camera; questCameraRequest.requestTimeStamp = theGame.GetEngineTimeAsSeconds(); } public function ResetQuestCameraRequest() { var cameraRequest : SQuestCameraRequest; questCameraRequest = cameraRequest; } event OnGameCameraPostTick( out moveData : SCameraMovementData, dt : float ) { var ent : CEntity; var playerPos : Vector; var angles : EulerAngles; var distance : float; /*if( thePlayer.IsInCombat() ) { distance = VecDistance2D( thePlayer.GetWorldPosition(), thePlayer.GetTarget().GetWorldPosition() ); } thePlayer.GetVisualDebug().AddText( 'Distance', "Distance form target: " + distance, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,2.f ), true, , Color( 0, 255, 0 ) ); */ if ( questCameraRequest.requestTimeStamp > 0 ) { if ( questCameraRequest.duration > 0 && questCameraRequest.requestTimeStamp + questCameraRequest.duration < theGame.GetEngineTimeAsSeconds() ) { ResetQuestCameraRequest(); return false; } if( questCameraRequest.lookAtTag ) { ent = theGame.GetEntityByTag( questCameraRequest.lookAtTag ); playerPos = GetWorldPosition(); playerPos.Z += 1.8f; angles = VecToRotation( ent.GetWorldPosition() - playerPos ); moveData.pivotRotationController.SetDesiredHeading( angles.Yaw ); moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch ); } else { if( questCameraRequest.requestYaw ) { angles = GetWorldRotation(); moveData.pivotRotationController.SetDesiredHeading( angles.Yaw + questCameraRequest.yaw ); } if( questCameraRequest.requestPitch ) { moveData.pivotRotationController.SetDesiredPitch( questCameraRequest.pitch ); } } } } var wasRunning : bool; var vel : float; var smoothTime : float; var constDamper : ConstDamper; var rotMultVel : float; public function UpdateCameraInterior( out moveData : SCameraMovementData, timeDelta : float ) { var camDist : float; var camOffset : float; var rotMultDest : float; var rotMult : float; var angles : EulerAngles; theGame.GetGameCamera().ChangePivotRotationController( 'ExplorationInterior' ); theGame.GetGameCamera().ChangePivotDistanceController( 'Default' ); theGame.GetGameCamera().ChangePivotPositionController( 'Default' ); // HACK moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController(); moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController(); moveData.pivotPositionController = theGame.GetGameCamera().GetActivePivotPositionController(); // END HACK moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition(), 15.f ); if ( !constDamper ) { constDamper = new ConstDamper in this; constDamper.SetDamp( 0.35f ); } if ( rawPlayerSpeed <= 0 || AbsF( AngleDistance( rawPlayerHeading, GetHeading() ) ) > 135 ) constDamper.Reset(); else if ( theGame.IsUberMovementEnabled() ) rotMult = 0.5f; else rotMult = 1.f; rotMult = constDamper.UpdateAndGet( timeDelta, rotMult ); //DampFloatSpring( rotMult, rotMultVel, rotMultDest, 4.f, timeDelta ); if ( AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) ) < 135.f && rawPlayerSpeed > 0 ) moveData.pivotRotationController.SetDesiredHeading( GetHeading(), rotMult ); else moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw ); moveData.pivotDistanceController.SetDesiredDistance( 1.5f ); angles = VecToRotation( GetMovingAgentComponent().GetVelocity() ); if ( AbsF( angles.Pitch ) < 8.f || bLAxisReleased ) moveData.pivotRotationController.SetDesiredPitch( -10.f ); else moveData.pivotRotationController.SetDesiredPitch( -angles.Pitch - 18.f ); if ( IsGuarded() ) moveData.pivotPositionController.offsetZ = 1.0f; else moveData.pivotPositionController.offsetZ = 1.3f; //if ( movementLockType == PMLT_NoSprint ) //{ if ( playerMoveType >= PMT_Run ) { //camDist = 0.3f; camDist = -0.5f; camOffset = 0.25; if ( !wasRunning ) { smoothTime = 1.f; wasRunning = true; } DampFloatSpring( smoothTime, vel, 0.1, 0.5, timeDelta ); } else { //camDist = -0.6f; camDist = 0.f; camOffset = 0.4f; smoothTime = 0.2f; wasRunning = false; } //camDist = theGame.GetGameplayConfigFloatValue( 'debugA' ); DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.3f, camDist, 0.3f ), smoothTime, timeDelta ); //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.5, camDist, camOffset ), smoothTime, timeDelta ); //} //else // DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ),theGame.GetGameplayConfigFloatValue( 'debugB' ),theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta ); //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( 0.7f, 0.f, 0.3 ), 0.4f, timeDelta ); } var wasBRAxisPushed : bool; protected function UpdateCameraChanneledSign( out moveData : SCameraMovementData, timeDelta : float ) : bool { var screenSpaceOffset : float; var screenSpaceOffsetFwd : float; var screenSpaceOffsetUp : float; var heading : float; var pitch : float; var playerToTargetRot : EulerAngles; var rightOffset : float = -20.f; var leftOffset : float = 15.f; var angles : EulerAngles; var vec : Vector; if( this.IsCurrentSignChanneled() && this.GetCurrentlyCastSign() != ST_Quen && this.GetCurrentlyCastSign() != ST_Yrden ) { theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' ); theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' ); // HACK moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController(); moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController(); // END HACK if ( GetCurrentlyCastSign() == ST_Axii ) leftOffset = 32.f; if ( oTCameraOffset != leftOffset && oTCameraOffset != rightOffset ) { if( ( interiorCamera && !moveTarget ) || ( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) < 0 ) ) oTCameraOffset = leftOffset; else oTCameraOffset = rightOffset; } if ( oTCameraOffset == leftOffset ) { screenSpaceOffset = 0.65f; oTCameraPitchOffset = 13.f; //moveData.pivotDistanceController.SetDesiredDistance( 0.5f, 3.f ); } else if ( oTCameraOffset == rightOffset ) { screenSpaceOffset = -0.65f; oTCameraPitchOffset = 13.f; //moveData.pivotDistanceController.SetDesiredDistance( 0.5f, 3.f ); } moveData.pivotPositionController.offsetZ = 1.3f; if ( !delayCameraOrientationChange ) { if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset ) { if ( bRAxisReleased ) { heading = moveData.pivotRotationValue.Yaw; pitch = moveData.pivotRotationValue.Pitch; } else { heading = moveData.pivotRotationValue.Yaw + oTCameraOffset; pitch = moveData.pivotRotationValue.Pitch; //+ oTCameraPitchOffset; } } else if ( GetOrientationTarget() == OT_Actor ) { if ( GetDisplayTarget() ) vec = GetDisplayTarget().GetWorldPosition() - GetWorldPosition(); else if ( slideTarget ) vec = slideTarget.GetWorldPosition() - GetWorldPosition(); else if ( GetTarget() ) vec = GetTarget().GetWorldPosition() - GetWorldPosition(); else vec = GetHeadingVector(); angles = VecToRotation( vec ); heading = angles.Yaw + oTCameraOffset; pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch; } else { angles = VecToRotation( GetHeadingVector() ); heading = angles.Yaw + oTCameraOffset; pitch = -angles.Pitch - oTCameraPitchOffset;//-angles.Pitch; } if ( !wasBRAxisPushed && ( !bRAxisReleased ) )//|| !lastAxisInputIsMovement ) ) wasBRAxisPushed = true; moveData.pivotRotationController.SetDesiredHeading( heading , 2.f ); moveData.pivotRotationController.SetDesiredPitch( pitch ); } else { moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f ); moveData.pivotRotationController.SetDesiredPitch( -oTCameraPitchOffset ); } if ( moveData.pivotRotationValue.Pitch <= 5.f && moveData.pivotRotationValue.Pitch >= -15.f ) { screenSpaceOffsetFwd = 1.8; screenSpaceOffsetUp = 0.4; } else if ( moveData.pivotRotationValue.Pitch > 0 ) { screenSpaceOffsetFwd = moveData.pivotRotationValue.Pitch*0.00727 + 1.275f; screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.2 ); screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.00727 + 0.4363f; screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, 0, 0.3 ); } else { if ( GetCurrentlyCastSign() == ST_Axii ) { screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.0425 + 0.8625f; screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.3 ); } else { screenSpaceOffsetFwd = -moveData.pivotRotationValue.Pitch*0.035 + 0.75f; screenSpaceOffsetFwd = ClampF( screenSpaceOffsetFwd, 1.5, 2.6 ); } screenSpaceOffsetUp = -moveData.pivotRotationValue.Pitch*0.005 + 0.325f; screenSpaceOffsetUp = ClampF( screenSpaceOffsetUp, 0.4, 0.5 ); } DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, screenSpaceOffsetFwd, screenSpaceOffsetUp ), 0.25f, timeDelta );//1.5,0.4 moveData.pivotDistanceController.SetDesiredDistance( 2.8f, 5.f ); moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() ); return true; } else { this.wasBRAxisPushed = false; return false; } } protected function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool { var screenSpaceOffset : float; var tempHeading : float; var cameraOffsetLeft : float; var cameraOffsetRight : float; if ( !specialAttackCamera ) return false; theGame.GetGameCamera().ForceManualControlHorTimeout(); theGame.GetGameCamera().ForceManualControlVerTimeout(); //if ( parent.delayCameraOrientationChange || parent.delayOrientationChange ) //{ cameraOffsetLeft = 30.f; cameraOffsetRight = -30.f; //} //else //{ // cameraOffsetLeft = 2.f; // cameraOffsetRight = -2.f; //} theGame.GetGameCamera().ChangePivotRotationController( 'SignChannel' ); theGame.GetGameCamera().ChangePivotDistanceController( 'SignChannel' ); // HACK moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController(); moveData.pivotDistanceController = theGame.GetGameCamera().GetActivePivotDistanceController(); if ( slideTarget ) tempHeading = VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() ); else tempHeading = GetHeading(); oTCameraPitchOffset = 0.f; if( ( interiorCamera && !moveTarget ) || ( AngleDistance( tempHeading, moveData.pivotRotationValue.Yaw ) < 0 ) ) oTCameraOffset = cameraOffsetLeft; else oTCameraOffset = cameraOffsetRight; if ( oTCameraOffset == cameraOffsetLeft ) { if ( delayCameraOrientationChange || delayOrientationChange ) { screenSpaceOffset = 0.75f; moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f ); moveData.pivotPositionController.offsetZ = 1.4f; moveData.pivotRotationController.SetDesiredPitch( -15.f ); } else { screenSpaceOffset = 0.7f; moveData.pivotDistanceController.SetDesiredDistance( 3.25f ); moveData.pivotPositionController.offsetZ = 1.2f; moveData.pivotRotationController.SetDesiredPitch( -10.f ); } } else if ( oTCameraOffset == cameraOffsetRight ) { if ( delayCameraOrientationChange || delayOrientationChange ) { screenSpaceOffset = -0.85f; moveData.pivotDistanceController.SetDesiredDistance( 1.6f, 3.f ); moveData.pivotPositionController.offsetZ = 1.4f; moveData.pivotRotationController.SetDesiredPitch( -15.f ); } else { screenSpaceOffset = -0.8f; moveData.pivotDistanceController.SetDesiredDistance( 3.25f ); moveData.pivotPositionController.offsetZ = 1.2f; moveData.pivotRotationController.SetDesiredPitch( -10.f ); } } else { moveData.pivotDistanceController.SetDesiredDistance( 1.25f, 3.f ); moveData.pivotPositionController.offsetZ = 1.3f; moveData.pivotRotationController.SetDesiredPitch( -5.5f ); } DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( screenSpaceOffset, 0.f, 0.f ), 1.f, timeDelta ); if ( !delayCameraOrientationChange ) { if ( moveTarget ) moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 0.5f ); else moveData.pivotRotationController.SetDesiredHeading( GetHeading() + oTCameraOffset, 1.f ); } else moveData.pivotRotationController.SetDesiredHeading( moveData.pivotRotationValue.Yaw, 1.f ); moveData.pivotPositionController.SetDesiredPosition( GetWorldPosition() ); return true; } private var fovVel : float; private var sprintOffset : Vector; private var previousOffset : bool; private var previousRotationVelocity : float; private var pivotRotationTimeStamp : float; protected function UpdateCameraSprint( out moveData : SCameraMovementData, timeDelta : float ) { var angleDiff : float; var camOffsetVector : Vector; var smoothSpeed : float; var camera : CCustomCamera; var camAngularSpeed : float; var playerToCamAngle : float; var useExplorationSprintCam : bool; camera = theGame.GetGameCamera(); if( camera ) { if ( sprintingCamera ) { //theGame.GetGameCamera().ForceManualControlHorTimeout(); theGame.GetGameCamera().ForceManualControlVerTimeout(); playerToCamAngle = AbsF( AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ) ); /*if ( theGame.GetGameplayConfigFloatValue( 'debugE' ) > 0.1f ) useExplorationSprintCam = !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax ); else*/ useExplorationSprintCam = false;// !IsInCombat() || ( moveTarget && VecDistance( moveTarget.GetWorldPosition(), GetWorldPosition() ) > findMoveTargetDistMax ); if ( useExplorationSprintCam ) { if ( playerToCamAngle <= 45 ) { theGame.GetGameCamera().ChangePivotRotationController( 'Sprint' ); // HACK moveData.pivotRotationController = theGame.GetGameCamera().GetActivePivotRotationController(); moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.25f ); moveData.pivotRotationController.SetDesiredPitch( -3.5f, 0.5f ); thePlayer.EnableManualCameraControl( true, 'Sprint' ); } else { thePlayer.EnableManualCameraControl( false, 'Sprint' ); } } else { if ( theGame.IsUberMovementEnabled() ) moveData.pivotRotationController.SetDesiredHeading( GetHeading(), 0.35f ); thePlayer.EnableManualCameraControl( true, 'Sprint' ); } if ( bRAxisReleased ) { if ( AbsF( rawLeftJoyRot ) > 25 ) angleDiff = AngleDistance( GetHeading(), moveData.pivotRotationValue.Yaw ); pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds(); previousRotationVelocity = 0.f; } else { if ( previousRotationVelocity <= 0 && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 ) { pivotRotationTimeStamp = theGame.GetEngineTimeAsSeconds(); previousRotationVelocity = AbsF( moveData.pivotRotationVelocity.Yaw ); } } if ( pivotRotationTimeStamp + 0.4f <= theGame.GetEngineTimeAsSeconds() && AbsF( moveData.pivotRotationVelocity.Yaw ) > 250 ) angleDiff = VecHeading( rawRightJoyVec ); if ( useExplorationSprintCam ) { if ( playerToCamAngle > 90 ) { camOffsetVector.X = 0.f; smoothSpeed = 1.f; } else if ( angleDiff > 15.f ) { camOffsetVector.X = -0.8; smoothSpeed = 1.f; previousOffset = true; } else if ( angleDiff < -15.f ) { camOffsetVector.X = 0.475f; smoothSpeed = 1.5f; previousOffset = false; } else { if ( previousOffset ) { camOffsetVector.X = -0.8; smoothSpeed = 1.5f; } else { camOffsetVector.X = 0.475f; smoothSpeed = 1.5f; } } camOffsetVector.Y = 1.4f; camOffsetVector.Z = 0.275f; } else { /*camOffsetVector.X = 0.f; camOffsetVector.Y = 0.4f; camOffsetVector.Z = 0.2f;*/ smoothSpeed = 0.75f; camOffsetVector.X = 0.f; camOffsetVector.Y = 1.f; camOffsetVector.Z = 0.2f; moveData.pivotRotationController.SetDesiredPitch( -10.f, 0.5f ); } DampVectorConst( sprintOffset, camOffsetVector, smoothSpeed, timeDelta ); moveData.cameraLocalSpaceOffset = sprintOffset; DampFloatSpring( camera.fov, fovVel, 70.f, 1.0, timeDelta ); } else { sprintOffset = moveData.cameraLocalSpaceOffset; DampFloatSpring( camera.fov, fovVel, 60.f, 1.0, timeDelta ); previousOffset = false; } } } function EnableSprintingCamera( flag : bool ) { if( !theGame.IsUberMovementEnabled() && !useSprintingCameraAnim ) { return; } super.EnableSprintingCamera( flag ); if ( !flag ) { thePlayer.EnableManualCameraControl( true, 'Sprint' ); } } protected function UpdateCameraCombatActionButNotInCombat( out moveData : SCameraMovementData, timeDelta : float ) { var vel : Vector; var heading : float; var pitch : float; var headingMult : float; var pitchMult : float; var camOffset : Vector; var buff : CBaseGameplayEffect; var runningAndAlertNear : bool; var desiredDist : float; if ( ( !IsCurrentSignChanneled() || GetCurrentlyCastSign() == ST_Quen || GetCurrentlyCastSign() == ST_Yrden ) && !specialAttackCamera && !IsInCombatActionFriendly() ) { buff = GetCurrentlyAnimatedCS(); runningAndAlertNear = GetPlayerCombatStance() == PCS_AlertNear && playerMoveType == PMT_Run && !GetDisplayTarget(); if ( runningAndAlertNear || ( GetPlayerCombatStance() == PCS_AlertFar && !IsInCombatAction() && !buff ) ) { camOffset.X = 0.f; camOffset.Y = 0.f; camOffset.Z = -0.1f; if ( runningAndAlertNear ) { moveData.pivotDistanceController.SetDesiredDistance( 4.f ); moveData.pivotPositionController.offsetZ = 1.5f; } } else { camOffset.X = 0.f; camOffset.Y = -1.5f; camOffset.Z = -0.2f; } DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( camOffset.X, camOffset.Y, camOffset.Z ), 0.4f, timeDelta ); sprintOffset = moveData.cameraLocalSpaceOffset; heading = moveData.pivotRotationValue.Yaw; if ( GetOrientationTarget() == OT_Camera || GetOrientationTarget() == OT_CameraOffset ) pitch = moveData.pivotRotationValue.Pitch; else if ( lastAxisInputIsMovement || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack || ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign && !IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen ) ) { theGame.GetGameCamera().ForceManualControlVerTimeout(); pitch = -20.f; } else pitch = moveData.pivotRotationValue.Pitch; headingMult = 1.f; pitchMult = 1.f; //if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) if( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign && ( GetEquippedSign() == ST_Aard || GetEquippedSign() == ST_Yrden ) && GetBehaviorVariable( 'alternateSignCast' ) == 1 ) { //theGame.GetGameCamera().ForceManualControlHorTimeout(); theGame.GetGameCamera().ForceManualControlVerTimeout(); pitch = -20.f; //DampVectorSpring( moveData.cameraLocalSpaceOffset, moveData.cameraLocalSpaceOffsetVel, Vector( theGame.GetGameplayConfigFloatValue( 'debugA' ), theGame.GetGameplayConfigFloatValue( 'debugB' ), theGame.GetGameplayConfigFloatValue( 'debugC' ) ), 0.4f, timeDelta ); } //vel = GetMovingAgentComponent().GetVelocity(); //if ( VecLength( vel ) > 0 && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge ) //{ /*theGame.GetGameCamera().ForceManualControlHorTimeout(); heading = GetHeading(); headingMult = 0.5f;*/ //} if ( IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Quen ) { pitch = moveData.pivotRotationValue.Pitch; } moveData.pivotRotationController.SetDesiredHeading( heading, ); moveData.pivotRotationController.SetDesiredPitch( pitch ); } } /*public function UpdateCameraForSpecialAttack( out moveData : SCameraMovementData, timeDelta : float ) : bool { return false; }*/ //------------------------------------------------------------------------------------------------------------------ event OnGameCameraExplorationRotCtrlChange() { if( substateManager ) { return substateManager.OnGameCameraExplorationRotCtrlChange( ); } return false; } /////////////////////////////////////////////////////////////////////////// // COMBAT MOVEMENT ORIENTATION /////////////////////////////////////////////////////////////////////////// //Rotation function SetCustomRotation( customRotationName : name, rotHeading : float, rotSpeed : float, activeTime : float, rotateExistingDeltaLocation : bool ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customRotationName ); movementAdjustor.Cancel( ticket ); ticket = movementAdjustor.CreateNewRequest( customRotationName ); movementAdjustor.Continuous( ticket ); movementAdjustor.ReplaceRotation( ticket ); movementAdjustor.RotateTo( ticket, rotHeading ); movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed ); if (rotSpeed == 0.0f) { movementAdjustor.AdjustmentDuration( ticket, activeTime ); } movementAdjustor.KeepActiveFor( ticket, activeTime ); movementAdjustor.RotateExistingDeltaLocation( ticket, rotateExistingDeltaLocation ); } function UpdateCustomRotationHeading( customRotationName : name, rotHeading : float ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customRotationName ); movementAdjustor.RotateTo( ticket, rotHeading ); } function SetCustomRotationTowards( customRotationName : name, target : CActor, rotSpeed : float, optional activeTime : float ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customRotationName ); movementAdjustor.Cancel( ticket ); ticket = movementAdjustor.CreateNewRequest( customRotationName ); movementAdjustor.Continuous( ticket ); movementAdjustor.ReplaceRotation( ticket ); movementAdjustor.RotateTowards( ticket, target ); movementAdjustor.MaxRotationAdjustmentSpeed( ticket, rotSpeed ); if (activeTime > 0.0f) { movementAdjustor.KeepActiveFor( ticket, activeTime ); } else { movementAdjustor.DontEnd( ticket ); } } //lock movement in dir function CustomLockMovement( customMovementName : name, heading : float ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customMovementName ); movementAdjustor.Cancel( ticket ); ticket = movementAdjustor.CreateNewRequest( customMovementName ); movementAdjustor.Continuous( ticket ); movementAdjustor.DontEnd( ticket ); movementAdjustor.LockMovementInDirection( ticket, heading ); } function BindMovementAdjustmentToEvent( customRotationName : name, eventName : CName ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customRotationName ); movementAdjustor.BindToEvent( ticket, eventName ); } function UpdateCustomLockMovementHeading( customMovementName : name, heading : float ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customMovementName ); movementAdjustor.LockMovementInDirection( ticket, heading ); } function CustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customMovementName ); movementAdjustor.Cancel( ticket ); ticket = movementAdjustor.CreateNewRequest( customMovementName ); movementAdjustor.Continuous( ticket ); movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist ); } function UpdateCustomLockDistance( customMovementName : name, maintainDistanceTo : CNode, minDist, maxDist : float ) { var movementAdjustor : CMovementAdjustor; var ticket : SMovementAdjustmentRequestTicket; movementAdjustor = GetMovingAgentComponent().GetMovementAdjustor(); ticket = movementAdjustor.GetRequest( customMovementName ); movementAdjustor.SlideTowards( ticket, maintainDistanceTo, minDist, maxDist ); } private var disableManualCameraControlStack : array; public function EnableManualCameraControl( enable : bool, sourceName : name ) { if ( !enable ) { if ( !disableManualCameraControlStack.Contains( sourceName ) ) { disableManualCameraControlStack.PushBack( sourceName ); } } else { disableManualCameraControlStack.Remove( sourceName ); } if ( disableManualCameraControlStack.Size() > 0 ) theGame.GetGameCamera().EnableManualControl( false ); else theGame.GetGameCamera().EnableManualControl( true ); } public function IsCameraControlDisabled( optional disabledBySourceName : name ) : bool { if ( disabledBySourceName ) return disableManualCameraControlStack.Contains( disabledBySourceName ); else return disableManualCameraControlStack.Size() > 0; } public function DisableManualCameraControlStackHasSource( sourceName : name ) : bool { return disableManualCameraControlStack.Contains( sourceName ); } public function ClearDisableManualCameraControlStack() { disableManualCameraControlStack.Clear(); theGame.GetGameCamera().EnableManualControl( true ); } function SetOrientationTarget( target : EOrientationTarget ) { if ( IsPCModeEnabled() && target == OT_Player ) { target = OT_Camera; } orientationTarget = target; } function GetOrientationTarget() : EOrientationTarget { return orientationTarget; } var customOrientationInfoStack : array; public function AddCustomOrientationTarget( orientationTarget : EOrientationTarget, sourceName : name ) { var customOrientationInfo : SCustomOrientationInfo; var i : int; if ( customOrientationInfoStack.Size() > 0 ) { for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 ) { if ( customOrientationInfoStack[i].sourceName == sourceName ) customOrientationInfoStack.Erase(i); } } customOrientationInfo.sourceName = sourceName; customOrientationInfo.orientationTarget = orientationTarget; customOrientationInfoStack.PushBack( customOrientationInfo ); SetOrientationTarget( orientationTarget ); } public function RemoveCustomOrientationTarget( sourceName : name ) { var customOrientationInfo : SCustomOrientationInfo; var i : int; if ( customOrientationInfoStack.Size() > 0 ) { for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 ) { if ( customOrientationInfoStack[i].sourceName == sourceName ) customOrientationInfoStack.Erase(i); } } else LogChannel( 'CustomOrienatation', "ERROR: Custom orientation cannot be removed, stack is already empty!!!" ); } protected function ClearCustomOrientationInfoStack() { customOrientationInfoStack.Clear(); } protected function GetCustomOrientationTarget( out infoStack : SCustomOrientationInfo ) : bool { var size : int; size = customOrientationInfoStack.Size(); if ( size <= 0 ) return false; else { infoStack = customOrientationInfoStack[ size - 1 ]; return true; } } public function SetOrientationTargetCustomHeading( heading : float, sourceName : name ) : bool { var i : int; if ( customOrientationInfoStack.Size() > 0 ) { for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 ) { if ( customOrientationInfoStack[i].sourceName == sourceName ) { customOrientationInfoStack[i].customHeading = heading; return true; } } } LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot set customHeading because stack is empty or sourceName is not found!!!" ); return false; } // returns the topmost OT_CustomHeading in stack public function GetOrientationTargetCustomHeading() : float { var i : int; if ( customOrientationInfoStack.Size() > 0 ) { for( i = customOrientationInfoStack.Size()-1; i>=0; i-=1 ) { if ( customOrientationInfoStack[i].orientationTarget == OT_CustomHeading ) { return customOrientationInfoStack[i].customHeading; } } } LogChannel( 'SetOrientationTargetCustomHeading', "ERROR: Cannot get customHeading because stack is empty or no OT_CustomHeading in stack!!!" ); return -1.f; } public function GetCombatActionOrientationTarget( combatActionType : ECombatActionType ) : EOrientationTarget { var newCustomOrientationTarget : EOrientationTarget; var targetEnt : CGameplayEntity; var targetActor : CActor; if ( GetCurrentStateName() == 'AimThrow' ) newCustomOrientationTarget = OT_CameraOffset; else { targetEnt = GetDisplayTarget(); targetActor = (CActor)targetEnt; if ( targetEnt ) { if ( targetActor ) { if ( moveTarget ) newCustomOrientationTarget = OT_Actor; else { if ( this.IsSwimming() ) newCustomOrientationTarget = OT_Camera; else if ( lastAxisInputIsMovement ) newCustomOrientationTarget = OT_Player; else newCustomOrientationTarget = OT_Actor; } } else { if ( combatActionType == CAT_Crossbow && targetEnt.HasTag( 'softLock_Bolt' ) ) newCustomOrientationTarget = OT_Actor; else { if ( this.IsSwimming() ) newCustomOrientationTarget = OT_Camera; else if ( lastAxisInputIsMovement ) newCustomOrientationTarget = OT_Player; else newCustomOrientationTarget = OT_Camera; } } } else { if ( IsUsingVehicle() )// || this.IsSwimming() ) newCustomOrientationTarget = OT_Camera; else if ( lastAxisInputIsMovement ) { if ( this.IsSwimming() ) { //if ( !bRAxisReleased // || ( GetOrientationTarget() == OT_Camera && ( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' ) ) ) newCustomOrientationTarget = OT_Camera; //else // newCustomOrientationTarget = OT_CustomHeading; } else newCustomOrientationTarget = OT_Player; } else newCustomOrientationTarget = OT_Camera; } } return newCustomOrientationTarget; } public function GetOrientationTargetHeading( orientationTarget : EOrientationTarget ) : float { var heading : float; if( orientationTarget == OT_Camera ) heading = VecHeading( theCamera.GetCameraDirection() ); else if( orientationTarget == OT_CameraOffset ) heading = VecHeading( theCamera.GetCameraDirection() ) - oTCameraOffset; else if( orientationTarget == OT_CustomHeading ) heading = GetOrientationTargetCustomHeading(); else if ( GetDisplayTarget() && orientationTarget == OT_Actor ) { if ( (CActor)( GetDisplayTarget() ) ) { //if ( GetPlayerCombatStance() == PCS_AlertNear ) heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() ); //else // heading = GetHeading(); } else { if ( GetDisplayTarget().HasTag( 'softLock_Bolt' ) ) heading = VecHeading( GetDisplayTarget().GetWorldPosition() - GetWorldPosition() ); else heading = GetHeading(); } } else heading = GetHeading(); return heading; } event OnDelayOrientationChange() { var delayOrientation : bool; var delayCameraRotation : bool; var moveData : SCameraMovementData; var time : float; time = 0.01f; if ( theInput.GetActionValue( 'CastSignHold' ) == 1.f ) { actionType = 0; if ( moveTarget ) delayOrientation = true; else { if ( !GetBIsCombatActionAllowed() ) delayOrientation = true; } } else if ( theInput.GetActionValue( 'ThrowItemHold' ) == 1.f ) { actionType = 3; delayOrientation = true; } else if ( theInput.GetActionValue( 'SpecialAttackHeavy' ) == 1.f ) { actionType = 2; if ( !slideTarget ) delayOrientation = true; else delayOrientation = true; } else if ( IsGuarded() && !moveTarget ) { actionType = 1; delayOrientation = true; } if ( delayOrientation ) { delayOrientationChange = true; theGame.GetGameCamera().ForceManualControlHorTimeout(); theGame.GetGameCamera().ForceManualControlVerTimeout(); AddTimer( 'DelayOrientationChangeTimer', time, true ); } if ( delayCameraRotation ) { delayCameraOrientationChange = true; theGame.GetGameCamera().ForceManualControlHorTimeout(); theGame.GetGameCamera().ForceManualControlVerTimeout(); AddTimer( 'DelayOrientationChangeTimer', time, true ); } } //This is also called from behgraph (e.g. SpecialHeavyAttack) event OnDelayOrientationChangeOff() { delayOrientationChange = false; delayCameraOrientationChange = false; RemoveTimer( 'DelayOrientationChangeTimer' ); //if ( !IsCameraLockedToTarget() ) // theGame.GetGameCamera().EnableManualControl( true ); } timer function DelayOrientationChangeTimer( time : float , id : int) { if ( ( actionType == 0 && theInput.GetActionValue( 'CastSignHold' ) == 0.f ) || ( actionType == 2 && theInput.GetActionValue( 'SpecialAttackHeavy' ) == 0.f ) || ( actionType == 3 && theInput.GetActionValue( 'ThrowItemHold' ) == 0.f ) || ( actionType == 1 && !IsGuarded() ) || ( VecLength( rawRightJoyVec ) > 0.f ) )//&& !( slideTarget && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Axii ) ) ) { OnDelayOrientationChangeOff(); } } public function SetCombatActionHeading( heading : float ) { combatActionHeading = heading; } public function GetCombatActionHeading() : float { return combatActionHeading; } protected function EnableCloseCombatCharacterRadius( flag : bool ) { var actor : CActor; actor = (CActor)slideTarget; if ( flag ) { this.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' ); if(actor) actor.GetMovingAgentComponent().SetVirtualRadius( 'CloseCombatCharacterRadius' ); } else { if ( this.IsInCombat() ) { GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' ); if(actor) actor.GetMovingAgentComponent().SetVirtualRadius( 'CombatCharacterRadius' ); } else { this.GetMovingAgentComponent().ResetVirtualRadius(); if(actor) actor.GetMovingAgentComponent().ResetVirtualRadius(); } } } /////////////////////////////////////////////////////////////////////////// // Soft Lock Logic private var isSnappedToNavMesh : bool; private var snapToNavMeshCachedFlag : bool; public function SnapToNavMesh( flag : bool ) { var comp : CMovingAgentComponent; comp = (CMovingAgentComponent)this.GetMovingAgentComponent(); if ( comp ) { comp.SnapToNavigableSpace( flag ); isSnappedToNavMesh = flag; } else { snapToNavMeshCachedFlag = flag; AddTimer( 'DelayedSnapToNavMesh', 0.2f ); } } public final function PlayRuneword4FX(optional weaponType : EPlayerWeapon) { var hasSwordDrawn : bool; var sword : SItemUniqueId; //we show fx only if overheal is greater than 1% - otherwise if we have a DoT and regen at the same time the health //jumps back and forth between 100% and 99.99% stating and stopping the fx over and over //needs to have sword drawn if(abilityManager.GetOverhealBonus() > (0.005 * GetStatMax(BCS_Vitality))) { hasSwordDrawn = HasAbility('Runeword 4 _Stats', true); if(!hasSwordDrawn && GetWitcherPlayer()) { if(weaponType == PW_Steel) { if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SteelSword, sword)) hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats'); } else if(weaponType == PW_Silver) { if(GetWitcherPlayer().GetItemEquippedOnSlot(EES_SilverSword, sword)) hasSwordDrawn = inv.ItemHasAbility(sword, 'Runeword 4 _Stats'); } } if(hasSwordDrawn) { if(!IsEffectActive('runeword_4', true)) PlayEffect('runeword_4'); } } } timer function DelayedSnapToNavMesh( dt : float, id : int) { SnapToNavMesh( snapToNavMeshCachedFlag ); } saved var navMeshSnapInfoStack : array; public function EnableSnapToNavMesh( source : name, enable : bool ) { if ( enable ) { if ( !navMeshSnapInfoStack.Contains( source ) ) navMeshSnapInfoStack.PushBack( source ); } else { if ( navMeshSnapInfoStack.Contains( source ) ) navMeshSnapInfoStack.Remove( source ); } if ( navMeshSnapInfoStack.Size() > 0 ) SnapToNavMesh( true ); else SnapToNavMesh( false ); } public function ForceRemoveAllNavMeshSnaps() { navMeshSnapInfoStack.Clear(); SnapToNavMesh( false ); } public function CanSprint( speed : float ) : bool { if( speed <= 0.8f ) { return false; } if ( thePlayer.GetIsSprintToggled() ) { } else if ( !sprintActionPressed ) { return false; } else if( !theInput.IsActionPressed('Sprint') || ( theInput.LastUsedGamepad() && IsInsideInteraction() && GetHowLongSprintButtonWasPressed() < 0.12 ) ) { return false; } if ( thePlayer.HasBuff( EET_OverEncumbered ) ) { return false; } if ( !IsSwimming() ) { if ( ShouldUseStaminaWhileSprinting() && !GetIsSprinting() && !IsInCombat() && GetStatPercents(BCS_Stamina) <= 0.9 ) { return false; } if( ( !IsCombatMusicEnabled() || IsInFistFightMiniGame() ) && ( !IsActionAllowed(EIAB_RunAndSprint) || !IsActionAllowed(EIAB_Sprint) ) ) { return false; } if( IsTerrainTooSteepToRunUp() ) { return false; } if( IsInCombatAction() ) { return false; } if( IsInAir() ) { return false; } } if( theGame.IsFocusModeActive() ) { return false; } return true; } public function SetTerrainPitch( pitch : float ) { terrainPitch = pitch; } public function IsTerrainTooSteepToRunUp() : bool { return terrainPitch <= disableSprintTerrainPitch; } public function SetTempLookAtTarget( actor : CGameplayEntity ) { tempLookAtTarget = actor; } private var beingWarnedBy : array; event OnBeingWarnedStart( sender : CActor ) { if ( !beingWarnedBy.Contains(sender) ) beingWarnedBy.PushBack(sender); } event OnBeingWarnedStop( sender : CActor ) { beingWarnedBy.Remove(sender); } event OnCanFindPath( sender : CActor ) { AddCanFindPathEnemyToList(sender,true); } event OnCannotFindPath( sender : CActor ) { AddCanFindPathEnemyToList(sender,false); } event OnBecomeAwareAndCanAttack( sender : CActor ) { AddEnemyToHostileEnemiesList( sender, true ); OnApproachAttack( sender ); } event OnBecomeUnawareOrCannotAttack( sender : CActor ) { AddEnemyToHostileEnemiesList( sender, false ); OnApproachAttackEnd( sender ); OnCannotFindPath(sender); } event OnApproachAttack( sender : CActor ) { AddEnemyToHostileEnemiesList( sender, true ); super.OnApproachAttack( sender ); } event OnApproachAttackEnd( sender : CActor ) { AddEnemyToHostileEnemiesList( sender, false ); super.OnApproachAttackEnd( sender ); } event OnAttack( sender : CActor ) { super.OnAttack( sender ); } event OnAttackEnd( sender : CActor ) { super.OnAttackEnd( sender ); } event OnHitCeiling() { substateManager.ReactOnHitCeiling(); } protected var hostileEnemies : array; //all enemies that are actively engaged in combat with the player (may or may not be visible by Geralt) private var hostileMonsters : array; // subgroup from hostileEnemies containing only monsters for sound system function AddEnemyToHostileEnemiesList( actor : CActor, add : bool ) { if ( add ) { RemoveTimer( 'RemoveEnemyFromHostileEnemiesListTimer' ); if ( !hostileEnemies.Contains( actor ) ) { hostileEnemies.PushBack( actor ); if( !actor.IsHuman() ) hostileMonsters.PushBack( actor ); } } else { if ( hostileEnemies.Size() == 1 ) { if ( !actor.IsAlive() || actor.IsKnockedUnconscious() ) { hostileEnemies.Remove( actor ); if( !actor.IsHuman() ) hostileMonsters.Remove( actor ); } else { // If we already waiting to remove an entity if( hostileEnemyToRemove ) { hostileEnemies.Remove( hostileEnemyToRemove ); if( !hostileEnemyToRemove.IsHuman() ) hostileMonsters.Remove( hostileEnemyToRemove ); } hostileEnemyToRemove = actor; AddTimer( 'RemoveEnemyFromHostileEnemiesListTimer', 3.f ); } } else { hostileEnemies.Remove( actor ); if( !actor.IsHuman() ) hostileMonsters.Remove( actor ); } } } public function ShouldEnableCombatMusic() : bool { var moveTargetNPC : CNewNPC; if ( thePlayer.GetPlayerMode().GetForceCombatMode() ) return true; else if ( !IsCombatMusicEnabled() ) { if ( IsInCombat() ) return true; else if ( IsThreatened() ) { moveTargetNPC = (CNewNPC)moveTarget; if ( moveTargetNPC.IsRanged() && hostileEnemies.Contains( moveTargetNPC ) ) return true; else return false; } else return false; } else if ( ( thePlayer.IsThreatened() && ( hostileEnemies.Size() > 0 || thePlayer.GetPlayerCombatStance() == PCS_AlertNear ) ) || IsInCombat() || finishableEnemiesList.Size() > 0 || isInFinisher ) return true; else return false; } public var canFindPathEnemiesList : array; public var disablecanFindPathEnemiesListUpdate : bool; private var lastCanFindPathEnemy : CActor; private var cachedMoveTarget : CActor; private var reachabilityTestId : int; private var reachabilityTestId2 : int; function AddCanFindPathEnemyToList( actor : CActor, add : bool ) { if ( disablecanFindPathEnemiesListUpdate ) return; if ( add && !canFindPathEnemiesList.Contains( actor ) ) { canFindPathEnemiesList.PushBack(actor); } else if ( !add ) { canFindPathEnemiesList.Remove(actor); if ( canFindPathEnemiesList.Size() <= 0 ) playerMode.UpdateCombatMode(); } } public function ClearCanFindPathEnemiesList( dt : float, id : int ) { canFindPathEnemiesList.Clear(); } public var finishableEnemiesList : array; function AddToFinishableEnemyList( actor : CActor, add : bool ) { if ( add && !finishableEnemiesList.Contains( actor ) ) { finishableEnemiesList.PushBack(actor); } else if ( !add ) { finishableEnemiesList.Remove(actor); } } private function UpdateFinishableEnemyList() { var i : int; i = 0; while ( i < finishableEnemiesList.Size() ) { if ( !finishableEnemiesList[ i ] ) { finishableEnemiesList.EraseFast( i ); } else { i += 1; } } } private timer function ClearFinishableEnemyList( dt : float, id : int ) { finishableEnemiesList.Clear(); } private var hostileEnemyToRemove : CActor; private timer function RemoveEnemyFromHostileEnemiesListTimer( time : float , id : int) { hostileEnemies.Remove( hostileEnemyToRemove ); if( hostileEnemyToRemove.IsMonster() ) hostileMonsters.Remove( hostileEnemyToRemove ); hostileEnemyToRemove = NULL; } private function ClearHostileEnemiesList() { hostileEnemies.Clear(); hostileMonsters.Clear(); canFindPathEnemiesList.Clear(); } private var moveTargets : array; //all hostileEnemies that Geralt is aware of. public function GetMoveTargets() : array { return moveTargets; } public function GetNumberOfMoveTargets() : int { return moveTargets.Size(); } protected var enableStrafe : bool; public function FindMoveTarget() { var moveTargetDists : array; var moveTargetCanPathFinds : array; var aPotentialMoveTargetCanFindPath : bool; var newMoveTarget : CActor; var actors : array; var currentHeading : float; var size, i : int; var playerToNewMoveTargetDist : float; var playerToMoveTargetDist : float; var confirmEmptyMoveTarget : bool; var newEmptyMoveTargetTimer : float; var wasVisibleInFullFrame : bool; var setIsThreatened : bool; var enemysTarget : CActor; var isEnemyInCombat : bool; var potentialMoveTargets : array; var onlyThreatTargets : bool; thePlayer.SetupEnemiesCollection( enemyCollectionDist, enemyCollectionDist, 10, 'None', FLAG_Attitude_Neutral + FLAG_Attitude_Hostile + FLAG_Attitude_Friendly + FLAG_OnlyAliveActors ); //if ( moveTarget ) // cachedMoveTarget = moveTarget; if ( GetCurrentStateName() != 'PlayerDialogScene' && IsAlive() )//&& !IsInCombatAction() )//GetBIsCombatActionAllowed() ) { GetVisibleEnemies( actors ); //Include enemies that geralt cannot see, but is hostile to him if ( hostileEnemies.Size() > 0 ) { for( i=0; i < hostileEnemies.Size() ; i+=1 ) { if ( !actors.Contains( hostileEnemies[i] ) ) actors.PushBack( hostileEnemies[i] ); } } //Include enemies that are technically dead, but can be finished off if ( finishableEnemiesList.Size() > 0 ) { for( i=0; i < finishableEnemiesList.Size() ; i+=1 ) { if ( !actors.Contains( finishableEnemiesList[i] ) ) actors.PushBack( finishableEnemiesList[i] ); } } //Check the last moveTarget for situation where enemy targets an ally when you round a corner if ( moveTarget && !actors.Contains( moveTarget ) ) actors.PushBack( moveTarget ); FilterActors( actors, onlyThreatTargets, false ); //Determine whether Player should be threatened if ( actors.Size() > 0 ) { setIsThreatened = false; if ( onlyThreatTargets ) { setIsThreatened = true; } else { for( i=0; i < actors.Size() ; i+=1 ) { if ( IsThreat( actors[i] ) ) { setIsThreatened = true; break; } else { enemysTarget = actors[i].GetTarget(); isEnemyInCombat = actors[i].IsInCombat(); if ( isEnemyInCombat && enemysTarget && GetAttitudeBetween( enemysTarget, this ) == AIA_Friendly && enemysTarget.isPlayerFollower ) { setIsThreatened = true; break; } } } } //After filtering you will only have either all hostile or all neutral npcs for( i = actors.Size()-1; i>=0; i-=1 ) { if ( ( !actors[i].IsAlive() && !finishableEnemiesList.Contains( actors[i] ) ) || actors[i].IsKnockedUnconscious() || this.GetUsedVehicle() == actors[i] || !actors[i].CanBeTargeted() ) { actors.EraseFast(i); } else if ( !IsThreatened() ) { if ( !WasVisibleInScaledFrame( actors[i], 1.f, 1.f ) ) actors.EraseFast(i); } } } else if ( moveTarget && IsThreat( moveTarget ) ) setIsThreatened = true; //SetIsThreatened( true ); else setIsThreatened = false; //SetIsThreatened( false ); if ( setIsThreatened ) { enemyCollectionDist = 50.f; SetIsThreatened( true ); } else { if ( IsThreatened() ) AddTimer( 'finishableEnemiesList', 1.f ); enemyCollectionDist = findMoveTargetDistMax; SetIsThreatened( false ); } moveTargets = actors; potentialMoveTargets = moveTargets; //MS: By default Geralt will not play PCS_AlertNear unless there is one guy among the hostile npcs that canBeStrafed if ( !moveTarget ) enableStrafe = false; if ( potentialMoveTargets.Size() > 0 ) { for ( i = 0; i < potentialMoveTargets.Size(); i += 1 ) { if ( potentialMoveTargets[i].CanBeStrafed() ) enableStrafe = true; if ( !potentialMoveTargets[i].GetGameplayVisibility() ) moveTargetDists.PushBack( 100.f ); //Put invisible enemies as the last choice for moveTarget else moveTargetDists.PushBack( VecDistance( potentialMoveTargets[i].GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() ) ); if ( canFindPathEnemiesList.Contains( potentialMoveTargets[i] ) ) { moveTargetCanPathFinds.PushBack( true ); aPotentialMoveTargetCanFindPath = true; } else { moveTargetCanPathFinds.PushBack( false ); } } if ( aPotentialMoveTargetCanFindPath ) { for ( i = moveTargetCanPathFinds.Size()-1 ; i >= 0; i-=1 ) { if ( !moveTargetCanPathFinds[i] ) { moveTargetCanPathFinds.EraseFast(i); potentialMoveTargets.EraseFast(i); moveTargetDists.EraseFast(i); } } } if ( moveTargetDists.Size() > 0 ) newMoveTarget = potentialMoveTargets[ ArrayFindMinF( moveTargetDists ) ]; } if ( newMoveTarget && newMoveTarget != moveTarget ) { if ( moveTarget ) { playerToNewMoveTargetDist = VecDistance( newMoveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() ); playerToMoveTargetDist = VecDistance( moveTarget.GetNearestPointInPersonalSpace( GetWorldPosition() ), GetWorldPosition() ); wasVisibleInFullFrame = WasVisibleInScaledFrame( moveTarget, 1.f, 1.f ) ; if ( !IsThreat( moveTarget ) || !wasVisibleInFullFrame || !IsEnemyVisible( moveTarget ) || ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) ) || !moveTarget.GetGameplayVisibility() || ( moveTarget.IsAlive() && moveTarget.IsKnockedUnconscious() ) || ( wasVisibleInFullFrame && IsEnemyVisible( moveTarget ) && playerToNewMoveTargetDist < playerToMoveTargetDist - 0.25f ) ) { SetMoveTarget( newMoveTarget ); } } else SetMoveTarget( newMoveTarget ); } if ( !IsThreatened() ) { if ( moveTarget && ( ( !moveTarget.IsAlive() && !finishableEnemiesList.Contains( moveTarget ) ) || !WasVisibleInScaledFrame( moveTarget, 0.8f, 1.f ) || VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() ) > theGame.params.MAX_THROW_RANGE ) ) { confirmEmptyMoveTarget = true; newEmptyMoveTargetTimer = 0.f; } } /*else if ( moveTarget && ( moveTarget.IsAlive() || finishableEnemiesList.Contains( moveTarget ) ) //&& moveTarget.GetGameplayVisibility() && hostileEnemies.Contains( moveTarget ) ) */ else if ( moveTarget && ( IsThreat( moveTarget ) || finishableEnemiesList.Contains( moveTarget ) ) ) { if ( !IsEnemyVisible( moveTarget ) ) { confirmEmptyMoveTarget = true; newEmptyMoveTargetTimer = 5.f; } else SetMoveTarget( moveTarget ); } else if ( IsInCombat() ) { confirmEmptyMoveTarget = true; newEmptyMoveTargetTimer = 1.0f; } if ( confirmEmptyMoveTarget ) { if ( newEmptyMoveTargetTimer < emptyMoveTargetTimer ) { bIsConfirmingEmptyTarget = false; emptyMoveTargetTimer = newEmptyMoveTargetTimer; } ConfirmEmptyMoveTarget( newEmptyMoveTargetTimer ); } } else SetIsThreatened( false ); //reactionsSystem if ( IsThreatened() && !IsInFistFightMiniGame() ) theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'CombatNearbyAction', 5.0, 18.0f, -1.f, -1, true ); //reactionSystemSearch else theGame.GetBehTreeReactionManager().RemoveReactionEvent( this, 'CombatNearbyAction'); //reactionSystemSearch // sending nearby monsters count as parameter to sound system theSound.SoundParameter( "monster_count", hostileMonsters.Size() ); } private function ConfirmEmptyMoveTarget( timeDelta : float ) { if ( !bIsConfirmingEmptyTarget ) { bIsConfirmingEmptyTarget = true; AddTimer( 'ConfirmEmptyTargetTimer', timeDelta ); } } private timer function ConfirmEmptyTargetTimer( time : float , id : int) { SetMoveTarget( NULL ); } var isInCombatReason : int; var canFindPathToEnemy : bool; var combatModeEnt : CEntity; var navDist : float; var directDist : float; var reachableEnemyWasTooFar : bool; var reachableEnemyWasTooFarTimeStamp : float; var reachablilityFailed : bool; var reachablilityFailedTimeStamp : float; public function ShouldEnableCombat( out unableToPathFind : bool, forceCombatMode : bool ) : bool { var shouldFindPathToNPCs : bool; var playerToTargetDist : float; var canFindPathToTarget : bool; var moveTargetNPC : CNewNPC; var currentTime : float; var currentTime2 : float; var isReachableEnemyTooFar : bool; var reachableEnemyWasTooFarTimeStampDelta : float; var reachablilityFailedTimeStampDelta : float; var currentTimeTemp : float; /*if ( GetIsSprinting() ) { unableToPathFind = true; isInCombatReason = 0; return false; }*/ if ( forceCombatMode && isSnappedToNavMesh ) return true; if ( !IsThreatened() ) { reachableEnemyWasTooFar = false; reachablilityFailed = false; isInCombatReason = 0; return false; } if( thePlayer.substateManager.GetStateCur() != 'CombatExploration' && !thePlayer.substateManager.CanChangeToState( 'CombatExploration' ) && thePlayer.substateManager.GetStateCur() != 'Ragdoll' ) //&& !thePlayer.substateManager.CanChangeToState( 'Ragdoll' ) ) ) { reachableEnemyWasTooFar = false; reachablilityFailed = false; isInCombatReason = 0; return false; } if ( moveTarget ) { canFindPathToEnemy = CanFindPathToTarget( unableToPathFind ); currentTimeTemp = EngineTimeToFloat( theGame.GetEngineTime() ); if ( canFindPathToEnemy ) isReachableEnemyTooFar = IsReachableEnemyTooFar(); if ( IsInCombat() ) { if ( canFindPathToEnemy ) { if ( forceCombatMode ) return true; reachablilityFailed = false; reachablilityFailedTimeStamp = currentTimeTemp; if ( reachableEnemyWasTooFar ) { if ( isReachableEnemyTooFar ) { currentTime = currentTimeTemp; if ( GetIsSprinting() ) reachableEnemyWasTooFarTimeStampDelta = 0.f; else reachableEnemyWasTooFarTimeStampDelta = 3.f; if ( currentTime > reachableEnemyWasTooFarTimeStamp + reachableEnemyWasTooFarTimeStampDelta ) { isInCombatReason = 0; unableToPathFind = true; return false; } } else reachableEnemyWasTooFar = false; } else { if ( isReachableEnemyTooFar ) { reachableEnemyWasTooFar = true; reachableEnemyWasTooFarTimeStamp = currentTimeTemp; } else reachableEnemyWasTooFar = false; } return true; } else { reachableEnemyWasTooFar = false; reachableEnemyWasTooFarTimeStamp = currentTimeTemp; if ( reachablilityFailed ) { if ( IsEnemyTooHighToReach() ) reachablilityFailedTimeStampDelta = 1.f; else reachablilityFailedTimeStampDelta = 5.f; currentTime2 = currentTimeTemp; if ( currentTime2 > reachablilityFailedTimeStamp + reachablilityFailedTimeStampDelta ) { unableToPathFind = true; return false; } } else { reachablilityFailed = true; reachablilityFailedTimeStamp = currentTimeTemp; } return true; } } else if ( canFindPathToEnemy ) { if ( forceCombatMode ) { reachableEnemyWasTooFar = false; return true; } reachablilityFailed = false; reachablilityFailedTimeStamp = currentTimeTemp; moveTargetNPC = (CNewNPC)moveTarget; playerToTargetDist = VecDistance( moveTarget.GetWorldPosition(), this.GetWorldPosition() ); /*if ( !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) ) { isInCombatReason = 0; return false; } else*/ if ( reachableEnemyWasTooFar && ( isReachableEnemyTooFar || !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), moveTarget.GetWorldPosition(), 0.4f ) ) ) { isInCombatReason = 0; return false; } else if ( playerToTargetDist <= findMoveTargetDistMin ) isInCombatReason = 1; else if ( ( moveTargetNPC.GetCurrentStance() == NS_Fly || moveTargetNPC.IsRanged() ) && hostileEnemies.Contains( moveTarget ) ) isInCombatReason = 2; else { isInCombatReason = 0; return false; } reachableEnemyWasTooFar = false; return true; } } else { reachableEnemyWasTooFar = false; reachablilityFailed = false; } isInCombatReason = 0; return false; } private function CanFindPathToTarget( out unableToPathFind : bool, optional forcedTarget : CNewNPC ) : bool { var moveTargetNPC : CNewNPC; var moveTargetsTemp : array; var i : int; var safeSpotTolerance : float; var ent : CEntity; moveTargetsTemp = moveTargets; for ( i = 0; i < moveTargetsTemp.Size(); i += 1 ) { moveTargetNPC = (CNewNPC)moveTargetsTemp[i]; if ( moveTargetNPC && moveTargetNPC.GetCurrentStance() == NS_Fly ) { isInCombatReason = 2; return true; } } switch ( navQuery.GetLastOutput( 0.4 ) ) { case EAsyncTastResult_Failure: { isInCombatReason = 0; return false; } case EAsyncTastResult_Success: { ent = navQuery.GetOutputClosestEntity(); if ( ent ) combatModeEnt = moveTarget; navDist = navQuery.GetOutputClosestDistance(); isInCombatReason = 1; return true; } case EAsyncTastResult_Pending: { return canFindPathToEnemy; } case EAsyncTastResult_Invalidated: { if ( IsInCombat() ) { if ( IsEnemyTooHighToReach() ) safeSpotTolerance = 0.f; else safeSpotTolerance = 3.f; } else safeSpotTolerance = 0.f; switch( navQuery.TestActorsList( ENavigationReachability_Any, this, moveTargetsTemp, safeSpotTolerance, 75.0 ) ) { case EAsyncTastResult_Failure: { isInCombatReason = 0; return false; } case EAsyncTastResult_Success: { ent = navQuery.GetOutputClosestEntity(); if ( ent ) combatModeEnt = moveTarget; navDist = navQuery.GetOutputClosestDistance(); isInCombatReason = 1; return true; } case EAsyncTastResult_Pending: { return canFindPathToEnemy; } case EAsyncTastResult_Invalidated: { if ( IsInCombat() ) return true; else return false; } } } } } private function IsReachableEnemyTooFar() : bool { //var navDistFailMax : float = 100.f; var navDistLimit : float = findMoveTargetDist; //25.f; var navDistDivisor : float = 2.f; var playerToTargetVector : Vector; directDist = VecDistance( combatModeEnt.GetWorldPosition(), thePlayer.GetWorldPosition() ); playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition(); if ( playerMode.GetForceCombatMode() || isInCombatReason == 2 ) return false; if ( ( playerToTargetVector.Z < 0.5 && navDist > navDistLimit && directDist < navDist/navDistDivisor ) ) return true; else return false; } private function IsEnemyTooHighToReach() : bool { var playerToTargetVector : Vector; playerToTargetVector = this.GetWorldPosition() - combatModeEnt.GetWorldPosition(); if ( playerToTargetVector.Z < -0.5f && !theGame.GetWorld().NavigationLineTest( this.GetWorldPosition(), combatModeEnt.GetWorldPosition(), 0.4f ) ) return true; else return false; } //Force Geralt to face an enemy for a moment before changing to another enemy public function LockToMoveTarget( lockTime : float ) { /*if ( IsMoveTargetChangeAllowed() ) { bMoveTargetChangeAllowed = false; AddTimer( 'DisableLockToMoveTargetTimer', lockTime ); }*/ } private timer function DisableLockToMoveTargetTimer( time : float , id : int) { if ( !this.IsActorLockedToTarget() ) { SetMoveTargetChangeAllowed( true ); } } public function SetMoveTargetChangeAllowed( flag : bool ) { //bMoveTargetChangeAllowed = flag; } public function IsMoveTargetChangeAllowed() : bool { return bMoveTargetChangeAllowed; } public function SetMoveTarget( actor : CActor ) { if ( !actor && ForceCombatModeOverride() ) return; if ( IsMoveTargetChangeAllowed() && moveTarget != actor ) { moveTarget = actor; bIsConfirmingEmptyTarget = false; RemoveTimer( 'ConfirmEmptyTargetTimer' ); if ( !moveTarget ) SetScriptMoveTarget( moveTarget ); } } private var isThreatened : bool; protected function SetIsThreatened( flag : bool ) { var allowSetIsThreatened : bool; allowSetIsThreatened = true; if ( ForceCombatModeOverride() ) { if ( flag || !moveTarget ) allowSetIsThreatened = true; else allowSetIsThreatened = false; } if ( allowSetIsThreatened ) { isThreatened = flag; } } public function ForceCombatModeOverride() : bool { if( this.GetPlayerMode().GetForceCombatMode() && canFindPathToEnemy && theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), moveTarget.GetBaseAttitudeGroup() ) == AIA_Hostile ) return true; else return false; } public function IsThreatened() : bool { return isThreatened; } public function EnableFindTarget( flag : bool ) { var target : CActor; if( IsActorLockedToTarget() ) { target = GetTarget(); if ( target && target.IsAlive() ) bCanFindTarget = flag; else bCanFindTarget = true; } else bCanFindTarget = flag; } public function UpdateDisplayTarget( optional forceUpdate : bool, optional forceNullActor : bool ) { var hud : CR4ScriptedHud; var tempTarget : CGameplayEntity; var angleDist1 : float; var angleDist2 : float; var nonActorTargetMult : float; var combatActionType : int; var currTarget : CActor; var interactionTarget : CInteractionComponent; var heading : float; if(theGame.IsDialogOrCutscenePlaying()) { currentSelectedDisplayTarget = NULL; if ( displayTarget ) ConfirmDisplayTarget( NULL ); return; } if ( forceNullActor ) currTarget = NULL; else currTarget = GetTarget(); currentSelectedDisplayTarget = currTarget; if ( currTarget && !currTarget.IsTargetableByPlayer() ) { currentSelectedDisplayTarget = NULL; ConfirmDisplayTarget( currentSelectedDisplayTarget ); return; } //Setting multiplier that increases non actor target priority nonActorTargetMult = 1.25; //Update the interaction icon hud = (CR4ScriptedHud)theGame.GetHud(); if ( !IsThreatened() ) { if ( !bLAxisReleased || lastAxisInputIsMovement ) { if ( currTarget ) angleDist1 = AbsF( AngleDistance( this.GetHeading(), VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) ); else angleDist1 = 360; if ( nonActorTarget ) angleDist2 = AbsF( AngleDistance( this.GetHeading(), VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) ); else angleDist2 = 360; } else { if ( currTarget ) angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) ); else angleDist1 = 360; if ( nonActorTarget ) angleDist2 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) ); else angleDist2 = 360; } } else { if ( !bLAxisReleased ) { if ( ShouldUsePCModeTargeting() ) { if ( currTarget ) angleDist1 = AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( currTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) ); else angleDist1 = 360; if ( nonActorTarget && IsInCombatAction() ) { angleDist2 = nonActorTargetMult * AbsF( AngleDistance( theCamera.GetCameraHeading(), VecHeading( nonActorTarget.GetWorldPosition() - theCamera.GetCameraPosition() ) ) ); } else angleDist2 = 360; } else { if ( currTarget ) angleDist1 = AbsF( AngleDistance( rawPlayerHeading, VecHeading( currTarget.GetWorldPosition() - this.GetWorldPosition() ) ) ); else angleDist1 = 360; if ( nonActorTarget && IsInCombatAction() ) { angleDist2 = nonActorTargetMult * AbsF( AngleDistance( rawPlayerHeading, VecHeading( nonActorTarget.GetWorldPosition() - this.GetWorldPosition() ) ) ); } else angleDist2 = 360; } } else { angleDist1 = 0; angleDist2 = 360; } } if ( angleDist1 < angleDist2 ) tempTarget = currTarget; else tempTarget = nonActorTarget; if ( slideTarget && IsInCombatAction() ) { combatActionType = (int)this.GetBehaviorVariable( 'combatActionType' ); if ( combatActionType == (int)CAT_Attack || ( combatActionType == (int)CAT_SpecialAttack && this.GetBehaviorVariable( 'playerAttackType' ) == 1.f ) || ( combatActionType == (int)CAT_ItemThrow ) || ( combatActionType == (int)CAT_CastSign && !IsCurrentSignChanneled() ) || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Axii ) || ( combatActionType == (int)CAT_CastSign && IsCurrentSignChanneled() && GetCurrentlyCastSign() == ST_Igni ) || combatActionType == (int)CAT_Dodge || combatActionType == (int)CAT_Roll ) { if ( combatActionType == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni && !IsCombatMusicEnabled() ) currentSelectedDisplayTarget = tempTarget; else currentSelectedDisplayTarget = slideTarget; } else currentSelectedDisplayTarget = tempTarget; } else if ( slideTarget && this.rangedWeapon && this.rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' && this.playerAiming.GetCurrentStateName() == 'Waiting' ) //( this.rangedWeapon.GetCurrentStateName() == 'State_WeaponShoot' || this.rangedWeapon.GetCurrentStateName() == 'State_WeaponAim' ) ) currentSelectedDisplayTarget = slideTarget; else currentSelectedDisplayTarget = tempTarget; interactionTarget = theGame.GetInteractionsManager().GetActiveInteraction(); if ( interactionTarget && !IsThreatened() && !( this.IsCastingSign() && this.IsCurrentSignChanneled() ) ) { tempTarget = (CGameplayEntity)interactionTarget.GetEntity(); if ( tempTarget && tempTarget != this.GetUsedVehicle() ) { currentSelectedDisplayTarget = tempTarget; SetDisplayTarget( currentSelectedDisplayTarget ); } } // disabling display for invisible targets if ( (CActor)currentSelectedDisplayTarget && !((CActor)currentSelectedDisplayTarget).GetGameplayVisibility() ) { currentSelectedDisplayTarget = NULL; } if ( displayTarget != currentSelectedDisplayTarget ) { if ( forceUpdate ) SetDisplayTarget( currentSelectedDisplayTarget ); else ConfirmDisplayTarget( currentSelectedDisplayTarget ); } } private var bConfirmDisplayTargetTimerEnabled : bool; private var displayTargetToConfirm : CGameplayEntity; private var currentSelectedDisplayTarget : CGameplayEntity; private function ConfirmDisplayTarget( targetToConfirm : CGameplayEntity ) { if ( targetToConfirm != displayTarget ) { displayTargetToConfirm = targetToConfirm; if( !bConfirmDisplayTargetTimerEnabled ) { bConfirmDisplayTargetTimerEnabled = true; if ( targetToConfirm ) AddTimer( 'ConfirmDisplayTargetTimer', 0.1f ); else AddTimer( 'ConfirmDisplayTargetTimer', 0.f ); } } } private timer function ConfirmDisplayTargetTimer( time : float, optional id : int) { if ( displayTargetToConfirm == currentSelectedDisplayTarget ) SetDisplayTarget( displayTargetToConfirm ); bConfirmDisplayTargetTimerEnabled = false; } protected function SetDisplayTarget( e : CGameplayEntity ) { var displayTargetActor : CActor; if ( e != displayTarget ) { displayTarget = e; displayTargetActor = (CActor)displayTarget; SetPlayerCombatTarget( displayTargetActor ); if ( displayTargetActor && !displayTargetActor.IsTargetableByPlayer()) { isDisplayTargetTargetable = false; } else if ( !displayTargetActor && displayTarget != nonActorTarget ) { isDisplayTargetTargetable = false; } else { isDisplayTargetTargetable = true; } } } public function GetDisplayTarget() : CGameplayEntity { return displayTarget; } private var isDisplayTargetTargetable : bool; public function IsDisplayTargetTargetable() : bool { return isDisplayTargetTargetable; } public var radialSlots : array; public function EnableRadialSlots( enable : bool, slotNames : array ) { var hud : CR4ScriptedHud; var module : CR4HudModuleRadialMenu; var i : int; hud = (CR4ScriptedHud)theGame.GetHud(); module = (CR4HudModuleRadialMenu)hud.GetHudModule("RadialMenuModule"); for(i=0; i { module.SetDesaturated( !enable, slotNames[i] ); } } public function IsEnemyInCone( source : CActor, coneHeading : Vector, coneDist, coneAngle : float, out newLockTarget : CActor ) : bool { var targets : array; var sourceToTargetDists : array; var i : int; var targetingInfo : STargetingInfo; //GetVisibleEnemies( targets ); //targets = FilterActors( targets ); targets = GetMoveTargets(); if ( targets.Size() > 0 ) { targetingInfo.source = this; targetingInfo.canBeTargetedCheck = true; targetingInfo.coneCheck = true; targetingInfo.coneHalfAngleCos = CosF( Deg2Rad( coneAngle * 0.5f ) ); targetingInfo.coneDist = coneDist; targetingInfo.coneHeadingVector = coneHeading; targetingInfo.distCheck = true; targetingInfo.invisibleCheck = true; targetingInfo.navMeshCheck = true; targetingInfo.inFrameCheck = false; targetingInfo.frameScaleX = 1.f; targetingInfo.frameScaleY = 1.f; targetingInfo.knockDownCheck = false; targetingInfo.knockDownCheckDist = 1.5f; targetingInfo.rsHeadingCheck = false; targetingInfo.rsHeadingLimitCos = 1.0f; for( i = targets.Size() - 1; i >= 0; i -= 1 ) { targetingInfo.targetEntity = targets[i]; if ( !IsEntityTargetable( targetingInfo ) ) targets.Erase( i ); } for ( i = 0; i < targets.Size(); i += 1 ) sourceToTargetDists.PushBack( VecDistance( source.GetWorldPosition(), targets[i].GetWorldPosition() ) ); if(sourceToTargetDists.Size() > 0) newLockTarget = targets[ ArrayFindMinF( sourceToTargetDists ) ]; else newLockTarget = NULL; } return targets.Size() > 0; } public function GetScreenSpaceLockTarget( sourceEnt : CGameplayEntity, coneAngle, coneDist, coneHeading : float, optional inFrameCheck : bool ) : CActor { var source : CActor; var sourcePos, targetPos : Vector; var targets : array; var sourceToTargetDists : array; var sourceCoord : Vector; var targetCoord : Vector; var i : int; var angleDiff : float; var sourceToTargetHeading : float; var sourceToTargetDist : float; var size : float; var targetingDist : float; var targetingInfo : STargetingInfo; var temp : int; // MAREK TODO : Need to use cached values of screenspace coords instead of calculating again //GetVisibleEnemies( targets ); //targets = FilterActors( targets ); source = (CActor)sourceEnt; targets = GetMoveTargets(); if ( this.IsPCModeEnabled() ) { if ( ( coneHeading > -45.f && coneHeading < 45.f ) || coneHeading > 135.f || coneHeading < -135.f ) { if ( coneHeading > 0 ) coneHeading = 180 - coneHeading; else coneHeading = 180 + coneHeading; } } /*if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 ) { if ( targets[0] && !IsThreat( targets[0] ) ) targets.Clear(); }*/ for( i = targets.Size() - 1; i >= 0; i -= 1 ) { if ( ( !targets[i].GetGameplayVisibility() || !IsThreat( targets[i] ) || !IsEnemyVisible( targets[i] ) || !this.CanBeTargetedIfSwimming( targets[i] ) ) && ( !IsCastingSign() || GetCurrentlyCastSign() != ST_Axii ) ) targets.Erase(i); } if ( source ) { temp = source.GetTorsoBoneIndex(); if ( temp < 0 ) sourcePos = source.GetWorldPosition(); else sourcePos = MatrixGetTranslation( source.GetBoneWorldMatrixByIndex( source.GetTorsoBoneIndex() ) ); } else sourcePos = sourceEnt.GetWorldPosition(); theCamera.WorldVectorToViewRatio( sourcePos, sourceCoord.X , sourceCoord.Y ); /*if ( !IsUsingVehicle() ) targetingDist = softLockDist; else*/ targetingDist = softLockDistVehicle; if ( targets.Size() > 0 ) { targetingInfo.source = this; targetingInfo.canBeTargetedCheck = true; targetingInfo.coneCheck = false; targetingInfo.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) ) targetingInfo.coneDist = targetingDist; targetingInfo.coneHeadingVector = Vector( 0.0f, 1.0f, 0.0f ); targetingInfo.distCheck = true; targetingInfo.invisibleCheck = true; targetingInfo.navMeshCheck = false; if ( inFrameCheck ) targetingInfo.inFrameCheck = true; else targetingInfo.inFrameCheck = false; targetingInfo.frameScaleX = 1.f; targetingInfo.frameScaleY = 1.f; targetingInfo.knockDownCheck = false; targetingInfo.knockDownCheckDist = softLockDist; if ( bRAxisReleased ) targetingInfo.rsHeadingCheck = false; else targetingInfo.rsHeadingCheck = true; targetingInfo.rsHeadingLimitCos = -0.5f; // = CosF( Deg2Rad( 120.0f ) ); for( i = targets.Size() - 1; i >= 0; i -= 1 ) { temp = targets[i].GetTorsoBoneIndex(); if ( temp < 0 ) targetPos = targets[i].GetWorldPosition(); else targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) ); theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y ); sourceToTargetHeading = VecHeading( targetCoord - sourceCoord ); angleDiff = AbsF( AngleDistance( coneHeading, sourceToTargetHeading ) ); targetingInfo.targetEntity = targets[i]; if ( !IsEntityTargetable( targetingInfo ) ) targets.Erase( i ); else if ( !bRAxisReleased && angleDiff > ( coneAngle * 0.5 ) ) targets.Erase( i ); else if ( targets[i] == sourceEnt ) targets.Erase( i ); /*if ( GetDisplayTarget() && IsInCombatAction() && GetBehaviorVariable( 'combatActionType') == (int)CAT_CastSign && GetCurrentlyCastSign() == ST_Igni ) { } else { targetingInfo.rsHeadingCheck = false; if ( !IsEntityTargetable( targetingInfo ) || angleDiff > ( coneAngle * 0.5 ) || targets[i] == sourceEnt ) targets.Erase( i ); }*/ } } size = targets.Size(); if ( size > 0 ) { for ( i = 0; i < targets.Size(); i += 1 ) { temp = targets[i].GetTorsoBoneIndex(); if ( temp < 0 ) targetPos = targets[i].GetWorldPosition(); else targetPos = MatrixGetTranslation( targets[i].GetBoneWorldMatrixByIndex( targets[i].GetTorsoBoneIndex() ) ); theCamera.WorldVectorToViewRatio( targetPos, targetCoord.X, targetCoord.Y ); sourceToTargetHeading = AbsF( VecHeading( targetCoord - sourceCoord ) ); angleDiff = AngleDistance( 180, sourceToTargetHeading ); sourceToTargetDist = VecDistance2D( sourceCoord, targetCoord ); sourceToTargetDists.PushBack( SinF( Deg2Rad( angleDiff ) ) * sourceToTargetDist ); } } if ( targets.Size() > 0 )//GetDisplayTarget() ) return targets[ ArrayFindMinF( sourceToTargetDists ) ]; else return NULL; } public function IsEntityTargetable( out info : STargetingInfo, optional usePrecalcs : bool ) : bool { var playerHasBlockingBuffs : bool; var sourceActor : CActor; var targetEntity : CEntity; var targetActor : CActor; var targetNPC : CNewNPC; var sourcePosition : Vector; var targetPosition : Vector; var direction : Vector; var sourceToTargetDist : float; var sourceCapsuleRadius : float; var mpac : CMovingPhysicalAgentComponent; var coneDistSq : float; var knockDownCheckDistSq : float; var sourceToTargetAngleDist : float; var b : bool; var infoSourceWorldPos : Vector; var infoTargetWorldPos : Vector; var finishEnabled : bool; if ( usePrecalcs ) { playerHasBlockingBuffs = targetingIn.playerHasBlockingBuffs; } else { playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness ); } if ( playerHasBlockingBuffs ) { return false; } sourceActor = info.source; targetEntity = info.targetEntity; if ( !sourceActor || !targetEntity ) { return false; } targetActor = (CActor)targetEntity; // "can be targeted" check if ( info.canBeTargetedCheck && !targetActor.CanBeTargeted() ) { return false; } // visibility check if ( info.invisibleCheck && !targetActor.GetGameplayVisibility() ) { return false; } sourcePosition = sourceActor.GetWorldPosition(); targetPosition = targetEntity.GetWorldPosition(); if ( targetActor ) { { // do not target mounted horses targetNPC = (CNewNPC)targetActor; if ( targetNPC ) { if ( targetNPC.IsHorse() && !targetNPC.GetHorseComponent().IsDismounted() ) { return false; } } } } if ( info.distCheck || info.knockDownCheck ) { if ( usePrecalcs ) { if ( targetActor ) { // radius is taken form the first actor sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( targetActor, sourceActor ) - targetingPrecalcs.playerRadius; } else { sourceToTargetDist = VecDistance2D( sourcePosition, targetPosition ) - targetingPrecalcs.playerRadius; } } else { if ( targetActor ) { sourceToTargetDist = Distance2DBetweenCapsules( sourceActor, targetActor ); } else { sourceToTargetDist = Distance2DBetweenCapsuleAndPoint( sourceActor, targetEntity ); } } } // distance check if ( info.distCheck ) { if ( sourceToTargetDist >= info.coneDist ) { return false; } } // prepare source to target direction if needed if ( info.coneCheck || info.rsHeadingCheck ) { direction = VecNormalize2D( targetPosition - sourcePosition ); } // cone check if ( info.coneCheck ) { if ( VecDot2D( direction, info.coneHeadingVector ) < info.coneHalfAngleCos ) { return false; } } // heading cone check if ( info.rsHeadingCheck ) { if ( usePrecalcs ) { if ( VecDot2D( direction, targetingIn.lookAtDirection ) < info.rsHeadingLimitCos ) { return false; } } else { if ( VecDot2D( direction, VecNormalize2D( GetLookAtPosition() - sourcePosition ) ) < info.rsHeadingLimitCos ) { return false; } } } // "in frame" check if ( info.inFrameCheck && !WasVisibleInScaledFrame( targetEntity, info.frameScaleX, info.frameScaleY ) ) { return false; } // navmesh check if ( info.navMeshCheck && !IsSwimming() ) { sourceCapsuleRadius = 0.1f; if ( usePrecalcs ) { sourceCapsuleRadius = targetingPrecalcs.playerRadius; } else { mpac = (CMovingPhysicalAgentComponent)sourceActor.GetMovingAgentComponent(); if ( mpac ) { sourceCapsuleRadius = mpac.GetCapsuleRadius(); } } if ( !theGame.GetWorld().NavigationLineTest( sourcePosition, targetPosition, sourceCapsuleRadius ) ) { return false; } } // knockdown check if ( info.knockDownCheck ) { // if actor is not alive if ( targetActor && !targetActor.IsAlive() ) { // and contains enabled "Finish" interaction finishEnabled = targetActor.GetComponent( 'Finish' ).IsEnabled(); if ( finishEnabled ) { // and is contained in finishable enemies list if ( finishableEnemiesList.Contains( targetActor ) ) { // and is too far to "finish" -> we cannot target it if ( sourceToTargetDist >= info.knockDownCheckDist ) { return false; } } } } } return true; } public function CanBeTargetedIfSwimming( actor : CActor, optional usePrecalcs : bool ) : bool { var subDepth : float; var isDiving : bool; if ( !actor ) { return false; } if ( usePrecalcs ) { isDiving = targetingIn.isDiving; } else { isDiving = IsSwimming() && OnCheckDiving(); } subDepth = ((CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent()).GetSubmergeDepth(); if ( isDiving ) { return ( subDepth < -1.0f ); } else { return ( subDepth >= -1.0f ); } } /* public function IsEntityTargetable( source : CActor, targetEntity : CGameplayEntity, coneCheck : bool, coneAngle, coneDist, coneHeading : float, distCheck, invisibleCheck, navMeshCheck : bool, inFrameCheck : bool, frameScaleX : float, frameScaleY : float, knockDownCheck : bool, knockDownCheckDist : float, rsHeadingCheck : bool, rsHeading : float, rsHeadingLimit : float) : bool { var targetActor : CActor; var targetNPC : CNewNPC; var direction : Vector; var sourceToTargetDist : float; var coneDistSq : float; var sourceCapsuleRadius : float; var knockDownCheckDistSq : float; var sourceToTargetAngleDist : float; var b : bool; var targetsHorse : W3HorseComponent; direction = VecNormalize2D( targetEntity.GetWorldPosition() - source.GetWorldPosition() ); targetActor = (CActor)targetEntity; if ( distCheck ) { if ( targetActor ) sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( source.GetWorldPosition() ) ); else sourceToTargetDist = VecDistanceSquared( source.GetWorldPosition(), targetEntity.GetWorldPosition() ); coneDistSq = coneDist * coneDist; } if ( knockDownCheck && targetActor ) knockDownCheckDistSq = knockDownCheckDist * knockDownCheckDist; if ( navMeshCheck && targetActor ) sourceCapsuleRadius = ((CMovingPhysicalAgentComponent)source.GetMovingAgentComponent()).GetCapsuleRadius(); if ( rsHeadingCheck ) sourceToTargetAngleDist = AngleDistance( VecHeading( GetLookAtPosition() - source.GetWorldPosition() ), VecHeading( targetEntity.GetWorldPosition() - source.GetWorldPosition() ) ); // do not target mounted horses if(targetActor) { targetNPC = (CNewNPC)targetActor; if(targetNPC) { targetsHorse = (W3HorseComponent)targetNPC.GetHorseComponent(); if(targetsHorse && targetsHorse.IsNotBeingUsed() ) return false; } } b = !coneCheck || AbsF( AngleDistance( coneHeading, VecHeading( direction ) ) ) < ( coneAngle * 0.5 ); b = b && ( !distCheck || sourceToTargetDist < coneDistSq ); b = b && ( !invisibleCheck || targetActor.GetGameplayVisibility() ); b = b && ( !navMeshCheck || (!IsSwimming() && theGame.GetWorld().NavigationLineTest( source.GetWorldPosition(), targetActor.GetWorldPosition(), sourceCapsuleRadius ) ) ); b = b && ( !inFrameCheck || WasVisibleInScaledFrame( targetEntity, frameScaleX, frameScaleY ) ); b = b && ( !rsHeadingCheck || ( rsHeading >= 0 && sourceToTargetAngleDist < 0 && sourceToTargetAngleDist >= ( rsHeadingLimit * -1 ) ) || ( rsHeading < 0 && sourceToTargetAngleDist >= 0 && sourceToTargetAngleDist <= rsHeadingLimit ) ); b = b && ( !knockDownCheck || !targetActor.GetComponent( 'Finish' ).IsEnabled() || ( targetActor.GetComponent( 'Finish' ).IsEnabled() && sourceToTargetDist < knockDownCheckDistSq ) ); if ( b ) return true; else return false; } */ private function FilterActors( out targets : array, out onlyThreatsReturned : bool, optional usePrecalcs : bool ) { var i : int; var size : int; var foundThreat : bool; var foundNonThreat : bool; var threatsCount : int; var tmpActor : CActor; foundThreat = false; foundNonThreat = false; size = targets.Size(); i = 0; threatsCount = 0; // after that loop first "threatsCount" targets will be "threat" for ( i = 0; i < size; i+=1 ) { if( IsThreat( targets[ i ], usePrecalcs ) ) { foundThreat = true; if ( i != threatsCount ) { tmpActor = targets[ i ]; targets[ i ] = targets[ threatsCount ]; targets[ threatsCount ] = tmpActor; } threatsCount += 1; } else { foundNonThreat = true; } } if ( foundThreat ) { onlyThreatsReturned = true; if ( foundNonThreat ) { targets.Resize( threatsCount ); } } } private function InternalFindTargetsInCone( out targets : array< CActor >, out outHeadingVector : Vector, optional usePrecalcs : bool ) { var size, i : int; var coneHalfAngleDot : float; var coneHeading : float; var coneHeadingVector : Vector; var position : Vector; var direction : Vector; var onlyThreatTargetsFound : bool; targets.Clear(); GetVisibleEnemies( targets ); //Include enemies that are technically dead, but can be finished off for( i = 0; i < finishableEnemiesList.Size() ; i+=1 ) { if ( !targets.Contains( finishableEnemiesList[i] ) ) { targets.PushBack( finishableEnemiesList[i] ); } } onlyThreatTargetsFound = false; FilterActors( targets, onlyThreatTargetsFound, true ); if ( IsCombatMusicEnabled() && targets.Size() > 0 && !onlyThreatTargetsFound && !IsThreat( targets[0], usePrecalcs ) ) { targets.Clear(); } coneHeading = 0.0f; coneHalfAngleDot = 0.0f; if ( ( orientationTarget == OT_Camera ) || ( orientationTarget == OT_CameraOffset ) ) { if ( usePrecalcs ) { coneHeading = targetingPrecalcs.cameraHeading; } else { coneHeading = theGame.GetGameCamera().GetHeading(); } coneHalfAngleDot = 0.5f; // = CosF( Deg2Rad( 120.f * 0.5f ) ); - Just use calculator... why not? this is constant. } else { if ( IsSwimming() ) { if ( usePrecalcs ) { coneHeading = targetingPrecalcs.cameraHeading; } else { coneHeading = theGame.GetGameCamera().GetHeading(); } coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) ); } else if ( bLAxisReleased ) { if( IsInCombatAction() ) { coneHeading = GetCombatActionHeading(); } else { if ( ShouldUsePCModeTargeting() ) coneHeading = theGame.GetGameCamera().GetHeading(); else coneHeading = cachedRawPlayerHeading; } if ( IsInCombat() ) { if ( ShouldUsePCModeTargeting() ) coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) ) else coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) ); } else { coneHalfAngleDot = -1.0f; } } else { if( IsInCombatAction() ) { coneHeading = GetCombatActionHeading(); } else { if ( ShouldUsePCModeTargeting() ) coneHeading = theGame.GetGameCamera().GetHeading(); else coneHeading = cachedRawPlayerHeading; } if ( ShouldUsePCModeTargeting() ) coneHalfAngleDot = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) ) else coneHalfAngleDot = 0.17364817766f; // = CosF( Deg2Rad( 160.f * 0.5f ) ); } coneHeadingVector = VecFromHeading( coneHeading ); position = this.GetWorldPosition(); for ( i = targets.Size() - 1; i >= 0; i -= 1 ) { if ( !targets[i] ) { targets.EraseFast(i); continue; } direction = VecNormalize2D( targets[i].GetWorldPosition() - position ); if ( VecDot2D( coneHeadingVector, direction ) < coneHalfAngleDot ) { targets.EraseFast( i ); } } } outHeadingVector = coneHeadingVector; } /////////////////////////////////////////////////////////////////////////// // (new) targeting function InitTargeting() { var consts : SR4PlayerTargetingConsts; if ( !targeting ) { targeting = new CR4PlayerTargeting in this; } if ( targeting ) { consts.softLockDistance = this.softLockDist; consts.softLockFrameSize = this.softLockFrameSize; targeting.SetConsts( consts ); } } function PrepareTargetingIn( actionCheck : bool, bufferActionType : EBufferActionType, actionInput : bool ) { var coneDist : float; if ( actionCheck && bufferActionType == EBAT_ItemUse ) { coneDist = findMoveTargetDist; } else if ( IsSwimming() ) { coneDist = theGame.params.MAX_THROW_RANGE; } else if ( ( GetPlayerCombatStance() == PCS_AlertNear ) && ( ( playerMoveType == PMT_Walk ) || ( playerMoveType == PMT_Idle ) ) ) { coneDist = softLockDist; } else { coneDist = findMoveTargetDist; } targetingIn.canFindTarget = this.bCanFindTarget; targetingIn.playerHasBlockingBuffs = thePlayer.HasBuff( EET_Confusion ) || thePlayer.HasBuff( EET_Hypnotized ) || thePlayer.HasBuff( EET_Blindness ) || thePlayer.HasBuff( EET_WraithBlindness ); targetingIn.isHardLockedToTarget = this.IsHardLockEnabled(); targetingIn.isActorLockedToTarget = this.IsActorLockedToTarget(); targetingIn.isCameraLockedToTarget = this.IsCameraLockedToTarget(); targetingIn.actionCheck = actionCheck; targetingIn.actionInput = actionInput; targetingIn.isInCombatAction = this.IsInCombatAction(); targetingIn.isLAxisReleased = this.bLAxisReleased; targetingIn.isLAxisReleasedAfterCounter = this.lAxisReleasedAfterCounter; targetingIn.isLAxisReleasedAfterCounterNoCA = this.lAxisReleasedAfterCounterNoCA; targetingIn.lastAxisInputIsMovement = this.lastAxisInputIsMovement; targetingIn.isAiming = this.playerAiming.GetCurrentStateName() == 'Aiming'; targetingIn.isSwimming = this.IsSwimming(); targetingIn.isDiving = this.IsSwimming() && OnCheckDiving(); targetingIn.isThreatened = this.IsThreatened(); targetingIn.isCombatMusicEnabled = this.IsCombatMusicEnabled(); targetingIn.isPcModeEnabled = this.IsPCModeEnabled(); targetingIn.isInParryOrCounter = this.isInParryOrCounter; targetingIn.shouldUsePcModeTargeting = this.ShouldUsePCModeTargeting(); targetingIn.bufferActionType = bufferActionType; targetingIn.orientationTarget = this.GetOrientationTarget(); targetingIn.coneDist = coneDist; // computed few lines above targetingIn.findMoveTargetDist = this.findMoveTargetDist; targetingIn.cachedRawPlayerHeading = this.cachedRawPlayerHeading; targetingIn.combatActionHeading = this.GetCombatActionHeading(); targetingIn.rawPlayerHeadingVector = VecFromHeading( this.rawPlayerHeading ); targetingIn.lookAtDirection = VecNormalize2D( this.GetLookAtPosition() - GetWorldPosition() ); targetingIn.moveTarget = this.moveTarget; targetingIn.aimingTarget = this.playerAiming.GetAimedTarget(); targetingIn.displayTarget = (CActor)this.displayTarget; targetingIn.finishableEnemies = this.finishableEnemiesList; targetingIn.hostileEnemies = this.hostileEnemies; targetingIn.defaultSelectionWeights = ProcessSelectionWeights(); } function ResetTargetingOut() { targetingOut.target = NULL; targetingOut.result = false; targetingOut.confirmNewTarget = false; targetingOut.forceDisableUpdatePosition = false; } function MakeFindTargetPrecalcs() { var mpac : CMovingPhysicalAgentComponent; targetingPrecalcs.playerPosition = thePlayer.GetWorldPosition(); targetingPrecalcs.playerHeading = thePlayer.GetHeading(); targetingPrecalcs.playerHeadingVector = thePlayer.GetHeadingVector(); targetingPrecalcs.playerHeadingVector.Z = 0; targetingPrecalcs.playerHeadingVector = VecNormalize2D( targetingPrecalcs.playerHeadingVector ); targetingPrecalcs.playerRadius = 0.5f; mpac = (CMovingPhysicalAgentComponent)thePlayer.GetMovingAgentComponent(); if ( mpac ) { targetingPrecalcs.playerRadius = mpac.GetCapsuleRadius(); } targetingPrecalcs.cameraPosition = theCamera.GetCameraPosition(); targetingPrecalcs.cameraDirection = theCamera.GetCameraDirection(); targetingPrecalcs.cameraHeadingVector = targetingPrecalcs.cameraDirection; targetingPrecalcs.cameraHeadingVector.Z = 0; targetingPrecalcs.cameraHeadingVector = VecNormalize2D( targetingPrecalcs.cameraHeadingVector ); targetingPrecalcs.cameraHeading = VecHeading( targetingPrecalcs.cameraHeadingVector ); } public function GetForceDisableUpdatePosition() : bool { return targetingOut.forceDisableUpdatePosition; } public function SetUseNativeTargeting( use : bool ) { useNativeTargeting = use; } protected function FindTarget( optional actionCheck : bool, optional action : EBufferActionType, optional actionInput : bool ) : CActor { if ( IsCombatMusicEnabled() && !IsInCombat() && reachableEnemyWasTooFar ) { playerMode.UpdateCombatMode(); } PrepareTargetingIn( actionCheck, action, actionInput ); if ( useNativeTargeting ) { targeting.BeginFindTarget( targetingIn ); targeting.FindTarget(); targeting.EndFindTarget( targetingOut ); } else { UpdateVisibleActors(); MakeFindTargetPrecalcs(); ResetTargetingOut(); FindTarget_Scripted(); } if ( targetingOut.result ) { if ( targetingOut.confirmNewTarget ) { ConfirmNewTarget( targetingOut.target ); } return targetingOut.target; } return NULL; } protected function FindTarget_Scripted() { var currentTarget : CActor; var newTarget : CActor; var selectedTarget : CActor; var displayTargetActor : CActor; var playerPosition : Vector; var playerHeadingVector : Vector; var cameraPosition : Vector; var cameraHeadingVector : Vector; var selectionHeadingVector : Vector; var targetingInfo : STargetingInfo; var selectionWeights : STargetSelectionWeights; var targets : array< CActor >; var isMoveTargetTargetable : bool; var targetChangeFromActionInput : bool; var retainCurrentTarget : bool; // caching data playerPosition = this.GetWorldPosition(); playerHeadingVector = targetingPrecalcs.playerHeadingVector; cameraPosition = theCamera.GetCameraPosition(); cameraHeadingVector = targetingPrecalcs.cameraHeadingVector; currentTarget = GetTarget(); if ( currentTarget ) { if ( IsHardLockEnabled() && currentTarget.IsAlive() && !currentTarget.IsKnockedUnconscious() ) { if ( VecDistanceSquared( playerPosition, currentTarget.GetWorldPosition() ) > 50.f * 50.0f ) { HardLockToTarget( false ); } else { targetingOut.target = currentTarget; targetingOut.result = true; return; } } GetVisualDebug().AddSphere('target', 1.0f, currentTarget.GetWorldPosition(), true, Color( 255, 255, 0 ), 1.0f ); } if ( bCanFindTarget && !IsActorLockedToTarget() ) { if ( !targetingIn.playerHasBlockingBuffs ) { InternalFindTargetsInCone( targets, selectionHeadingVector, true ); } targetingInfo.source = this; targetingInfo.canBeTargetedCheck = true; targetingInfo.coneCheck = false; targetingInfo.coneHalfAngleCos = 1.0f; targetingInfo.coneDist = targetingIn.coneDist; targetingInfo.distCheck = true; targetingInfo.invisibleCheck = true; targetingInfo.navMeshCheck = false; //true; if ( ShouldUsePCModeTargeting() ) targetingInfo.inFrameCheck = false; else targetingInfo.inFrameCheck = true; targetingInfo.frameScaleX = 1.0f; targetingInfo.frameScaleY = 1.0f; targetingInfo.knockDownCheck = false; targetingInfo.knockDownCheckDist = 1.5f; targetingInfo.rsHeadingCheck = false; targetingInfo.rsHeadingLimitCos = 1.0f; if ( currentTarget ) { targetingInfo.targetEntity = currentTarget; if ( !IsEntityTargetable( targetingInfo, true ) ) { currentTarget = NULL; } if ( currentTarget && !CanBeTargetedIfSwimming( currentTarget, true ) ) { currentTarget = NULL; } } isMoveTargetTargetable = false; if ( moveTarget ) { if ( CanBeTargetedIfSwimming( moveTarget, true ) ) { targetingInfo.targetEntity = moveTarget; targetingInfo.coneDist = findMoveTargetDist; targetingInfo.inFrameCheck = false; if ( IsEntityTargetable( targetingInfo, true ) ) { isMoveTargetTargetable = true; } } } // checking "standard" cone dist again targetingInfo.coneDist = targetingIn.coneDist; if ( !targetingIn.playerHasBlockingBuffs ) { RemoveNonTargetable( targets, targetingInfo, selectionHeadingVector ); } newTarget = NULL; if ( this.playerAiming.GetCurrentStateName() == 'Aiming' ) { newTarget = this.playerAiming.GetAimedTarget(); if ( !newTarget ) { selectionWeights.angleWeight = 1.f; selectionWeights.distanceWeight = 0.f; selectionWeights.distanceRingWeight = 0.f; selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true ); newTarget = selectedTarget; } } else if ( IsSwimming() ) { selectionWeights.angleWeight = 0.9f; selectionWeights.distanceWeight = 0.1f; selectionWeights.distanceRingWeight = 0.f; selectedTarget = SelectTarget( targets, true, cameraPosition, cameraHeadingVector, selectionWeights, true ); newTarget = selectedTarget; } else if ( IsThreatened() ) { // Change locked enemy when the current one becomes invisible if ( IsCameraLockedToTarget() ) { if ( currentTarget && !currentTarget.GetGameplayVisibility() ) { ForceSelectLockTarget(); } } displayTargetActor = (CActor)displayTarget; selectedTarget = SelectTarget( targets, true, playerPosition, selectionHeadingVector, targetingIn.defaultSelectionWeights, true ); if ( !selectedTarget ) { targetingOut.forceDisableUpdatePosition = true; } targetChangeFromActionInput = targetingIn.actionInput && !lAxisReleasedAfterCounter; if ( selectedTarget && ( !IsThreat( currentTarget, true ) || ShouldUsePCModeTargeting() || ( !IsInCombatAction() && !lAxisReleasedAfterCounterNoCA ) || targetChangeFromActionInput ) ) { newTarget = selectedTarget; } else if ( displayTargetActor && ( ( bLAxisReleased && !ShouldUsePCModeTargeting() )|| IsInCombatAction() ) && ( displayTargetActor.IsAlive() || finishableEnemiesList.Contains( displayTargetActor ) ) && displayTargetActor.GetGameplayVisibility() && ( IsEnemyVisible( displayTargetActor ) || finishableEnemiesList.Contains( displayTargetActor ) ) && this.CanBeTargetedIfSwimming( displayTargetActor, true ) && IsThreat( displayTargetActor, true ) && WasVisibleInScaledFrame( displayTargetActor, 1.f, 1.f ) ) { newTarget = displayTargetActor; } // target closest enemy immediately when transitioning from running/sprint to walk/idle, // but when you are already in walk/idle player should hit air after he kills his target, he should only target closest enemy when that enmy is within his field of vision else if ( moveTarget && isMoveTargetTargetable && ( !IsInCombatAction() || isInParryOrCounter || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) ) { newTarget = moveTarget; } else { newTarget = NULL; } } else { retainCurrentTarget = false; if ( lAxisReleasedAfterCounterNoCA ) { if ( lastAxisInputIsMovement && !this.IsSwimming()) { selectionWeights.angleWeight = 0.375f; selectionWeights.distanceWeight = 0.275f; selectionWeights.distanceRingWeight = 0.35f; selectedTarget = SelectTarget( targets, false, playerPosition, playerHeadingVector, selectionWeights, true ); if ( currentTarget != selectedTarget ) { targetingInfo.targetEntity = currentTarget; if ( IsEntityTargetable( targetingInfo, true ) && currentTarget.IsAlive() ) { retainCurrentTarget = true; } } } else { selectionWeights.angleWeight = 0.75f; selectionWeights.distanceWeight = 0.125f; selectionWeights.distanceRingWeight = 0.125f; selectedTarget = SelectTarget( targets, false, cameraPosition, cameraHeadingVector, selectionWeights, true ); } } else { selectionWeights.angleWeight = 0.6f; selectionWeights.distanceWeight = 0.4f; selectionWeights.distanceRingWeight = 0.f; selectedTarget = SelectTarget( targets, true, playerPosition, targetingIn.rawPlayerHeadingVector, selectionWeights, true ); } if ( retainCurrentTarget ) { newTarget = currentTarget; } else if ( IsInCombatAction() && GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.0f ) { newTarget = moveTarget; } else if ( selectedTarget ) { newTarget = selectedTarget; } else { newTarget = NULL; } } targetingOut.confirmNewTarget = true; } else { newTarget = NULL; } targetingOut.result = true; targetingOut.target = newTarget; } function UpdateVisibleActors() { var i : int; var now : float; now = theGame.GetEngineTimeAsSeconds(); for ( i = visibleActors.Size() - 1; i >= 0; i-=1 ) { // wasn't visible for more than 1 second if ( ( now - visibleActorsTime[i] ) > 1.0f ) { visibleActors.EraseFast( i ); visibleActorsTime.EraseFast( i ); } } } function RemoveNonTargetable( out targets : array< CActor >, out info : STargetingInfo, selectionHeadingVector : Vector ) { var i : int; var cameraPosition : Vector; var cameraDirection : Vector; var nonCombatCheck : bool; var playerToCamPlaneDist : float; var targetToCamPlaneDist : float; if ( targets.Size() == 0 ) { return; } nonCombatCheck = bLAxisReleased && !IsInCombat(); // first, let's prepare targeting info (so that we don't need to do it in each loop step) if ( nonCombatCheck ) { info.coneHeadingVector = targetingPrecalcs.playerHeadingVector; if ( lastAxisInputIsMovement ) { info.coneHeadingVector = selectionHeadingVector; info.invisibleCheck = false; info.coneCheck = true; info.coneHalfAngleCos = 0.76604444311f; // = CosF( Deg2Rad( 80.0f * 0.5f ) ) } else { info.invisibleCheck = false; info.frameScaleX = 0.9f; info.frameScaleY = 0.9f; } } else { info.coneHeadingVector = Vector( 0.0f, 0.0f, 0.0f ); //MS: ConeCheck is false because it's already been filtered by InternalFindTargetsInCone if ( IsInCombat() ) { info.inFrameCheck = false; } else { if ( !bLAxisReleased ) { info.coneCheck = true; if ( this.IsSwimming() ) info.coneHalfAngleCos = -1; // = CosF( Deg2Rad( 360.0f * 0.5f ) ) else info.coneHalfAngleCos = 0.86602540378f; // = CosF( Deg2Rad( 60.0f * 0.5f ) ) info.coneHeadingVector = targetingIn.rawPlayerHeadingVector; } } } cameraPosition = theCamera.GetCameraPosition(); cameraDirection = targetingPrecalcs.cameraDirection; playerToCamPlaneDist = VecDot2D( cameraDirection, this.GetWorldPosition() - cameraPosition ); // then, using prepared info let's filter out invalid targets for( i = targets.Size() - 1; i >= 0; i -= 1 ) { info.targetEntity = targets[i]; if ( !CanBeTargetedIfSwimming( targets[i], true ) ) { targets.EraseFast( i ); } else if ( !IsEntityTargetable( info, true ) ) { targets.EraseFast( i ); } else { if ( nonCombatCheck && !lastAxisInputIsMovement ) { // removing targets between camera and player targetToCamPlaneDist = VecDot2D( cameraDirection, targets[i].GetWorldPosition() - cameraPosition ); if ( targetToCamPlaneDist < playerToCamPlaneDist ) { targets.EraseFast( i ); } } } } } var combatModeColor : Color; public function CombatModeDebug() { var visualDebug : CVisualDebug = GetVisualDebug(); var naviQueryMsg : string; var naviQueryMsg1 : string; var naviQueryMsg2 : string; var navSnapMsg : string; var i : int; if ( IsCombatMusicEnabled() ) visualDebug.AddText( 'CombatMusic', "CombatMusic : On", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 255, 255, 255 ) ); else visualDebug.AddText( 'CombatMusic', "CombatMusic : Off", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.7f ), true, , Color( 0, 0, 0 ) ); if ( GetPlayerMode().GetForceCombatMode() ) visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : TRUE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 255, 255, 255 ) ); else visualDebug.AddText( 'ForcedCombatMode', "ForcedCombatMode : FALSE", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.6f ), true, , Color( 0, 0, 0 ) ); if ( IsThreatened() ) { if ( IsInCombat() ) visualDebug.AddText( 'CombatMode', "CombatMode : AlertNear/Far", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 0, 0 ) ); else visualDebug.AddText( 'CombatMode', "CombatMode : CombatExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 255, 255, 0 ) ); } else visualDebug.AddText( 'CombatMode', "CombatMode : NormalExploration", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.5f ), true, , Color( 0, 255, 0 ) ); visualDebug.AddText( 'NaviQuery', naviQueryMsg, combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', naviQueryMsg1, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', naviQueryMsg2, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); if ( isInCombatReason == 0 ) visualDebug.AddText( 'CombatModeReason', "CombatModeReason : ", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 125, 125, 125 ) ); else if ( isInCombatReason == 1 ) visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Geralt CAN pathfind to NPC", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) ); else if ( isInCombatReason == 2 ) visualDebug.AddText( 'CombatModeReason', "CombatModeReason : An NPC is flying or ranged", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) ); else if ( isInCombatReason == 2 ) visualDebug.AddText( 'CombatModeReason', "CombatModeReason : Forced Combat Mode", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.4f ), true, , Color( 255, 0, 0 ) ); if ( reachableEnemyWasTooFar ) { combatModeColor.Red = 255; combatModeColor.Green = 255; combatModeColor.Blue = 0; } else { combatModeColor.Red = 0; combatModeColor.Green = 255; combatModeColor.Blue = 0; } if ( IsThreatened() ) { switch ( navQuery.GetLastOutput( 2.0 ) ) { case EAsyncTastResult_Failure: { if ( this.playerMode.GetForceCombatMode() ) { if ( isSnappedToNavMesh ) { visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "Naviquery : Snapped So no need for query", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); } else { visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); } } else { visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "Naviquery : Failed", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); } break; } case EAsyncTastResult_Success: { visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "Naviquery : Success (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "Naviquery : Success (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); break; } case EAsyncTastResult_Pending: { visualDebug.AddText( 'NaviQuery', combatModeEnt.GetName(), combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "Naviquery : Pending (navDist: " + navDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "Naviquery : Pending (directDist: " + directDist + ")", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); break; } case EAsyncTastResult_Invalidated: { visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "Naviquery : Invalidated", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); break; } } } else { visualDebug.AddText( 'NaviQuery', "", combatModeEnt.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery1', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.3f ), true, , combatModeColor ); visualDebug.AddText( 'NaviQuery2', "", thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.2f ), true, , combatModeColor ); } if ( navMeshSnapInfoStack.Size() > 0 ) { for ( i = navMeshSnapInfoStack.Size()-1; i >= 0; i -= 1 ) { navSnapMsg = navSnapMsg + navMeshSnapInfoStack[i] + " "; } visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Enabled, Sources : " + navSnapMsg, thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 255, 255, 255 ) ); } else visualDebug.AddText( 'NavMeshSnap', "NavMeshSnap: Disabled" , thePlayer.GetWorldPosition() + Vector( 0.f,0.f,1.1f ), true, , Color( 0, 0, 0 ) ); } function IsCombatMusicEnabled() : bool { if ( theSound.GetCurrentGameState() == ESGS_UnderwaterCombat || theSound.GetCurrentGameState() == ESGS_Combat || theSound.GetCurrentGameState() == ESGS_CombatMonsterHunt || theSound.GetCurrentGameState() == ESGS_FocusUnderwaterCombat ) return true; else return false; } function IsSoundStateCombatMusic( gameState : ESoundGameState ) : bool { if ( gameState == ESGS_UnderwaterCombat || gameState == ESGS_Combat || gameState == ESGS_CombatMonsterHunt || gameState == ESGS_FocusUnderwaterCombat ) return true; else return false; } private function ConfirmNewTarget( actorToConfirm : CActor ) { var leftJoyRotLimit : float = 1.f; var target : CActor; target = GetTarget(); //MS: When Player pushes stick in npcs direction, he needs to push the stick beyond leftJoyRotLimit in order to change targets if ( !target || !moveTarget || ( target && ( !IsThreat( target ) || !target.IsAlive() ) ) || VecLength( rawLeftJoyVec ) < 0.7f || ( IsInCombatAction() && ( ( GetBehaviorVariable( 'combatActionType') == (int)CAT_Dodge ) || ( VecLength( rawLeftJoyVec ) >= 0.7f && ( prevRawLeftJoyRot >= ( rawLeftJoyRot + leftJoyRotLimit ) || prevRawLeftJoyRot <= ( rawLeftJoyRot - leftJoyRotLimit ) || AbsF( AngleDistance( cachedRawPlayerHeading, VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ) ) ) > 60 ) ) ) ) || ( !IsInCombatAction() && ( !rangedWeapon || ( rangedWeapon.GetCurrentStateName() != 'State_WeaponHolster' ) ) ))//&& rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' ) && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) ) { SetPrevRawLeftJoyRot(); if ( actorToConfirm != target ) { SetTarget( actorToConfirm ); } } } protected function SelectTarget( targets : array< CActor >, useVisibilityCheck : bool, sourcePosition : Vector, headingVector : Vector, selectionWeights : STargetSelectionWeights, optional usePrecalcs : bool ) : CActor { var i : int; var target : CActor; var selectedTarget : CActor; var currentTarget : CActor; var playerPosition : Vector; var distanceToPlayer : float; var priority : float; var maxPriority : float; var now : float; var remove : bool; var visibleActorIndex : int; if ( useVisibilityCheck ) { currentTarget = this.GetTarget(); playerPosition = this.GetWorldPosition(); now = theGame.GetEngineTimeAsSeconds(); for ( i = targets.Size() - 1; i >= 0; i-=1 ) { target = targets[ i ]; if ( target != currentTarget && ( !IsPCModeEnabled() && !WasVisibleInScaledFrame( target, softLockFrameSize, softLockFrameSize ) ) ) { remove = true; visibleActorIndex = visibleActors.FindFirst( target ); if ( visibleActorIndex != -1 ) { if ( usePrecalcs ) { distanceToPlayer = Distance2DBetweenCapsuleAndPoint( target, this ) - targetingPrecalcs.playerRadius; } else { distanceToPlayer = Distance2DBetweenCapsules( this, target ); } // if within soft lock distance and soft lock visibility duration -> don't remove yet if ( distanceToPlayer < this.softLockDist && ( now - visibleActorsTime[ i ] ) < 1.0f ) { remove = false; } } if ( remove ) { targets.EraseFast( i ); } } else { visibleActorIndex = visibleActors.FindFirst( target ); if ( visibleActorIndex == -1 ) { visibleActors.PushBack( target ); visibleActorsTime.PushBack( now ); } else { visibleActorsTime[ visibleActorIndex ] = now; } } } } selectedTarget = NULL; maxPriority = -1.0f; for( i = targets.Size() - 1; i >= 0; i-=1 ) { priority = CalcSelectionPriority( targets[ i ], selectionWeights, sourcePosition, headingVector ); if ( priority > maxPriority ) { maxPriority = priority; selectedTarget = targets[ i ]; } } //LogChannel( 'selectedTarget', selectedTarget ); return selectedTarget; } function Distance2DBetweenCapsuleAndPoint( actor : CActor, entity : CEntity ) : float { var distance : float; var mpac : CMovingPhysicalAgentComponent; distance = VecDistance2D( actor.GetWorldPosition(), entity.GetWorldPosition() ); mpac = (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent(); if ( mpac ) { distance -= mpac.GetCapsuleRadius(); } return distance; } function Distance2DBetweenCapsules( actor1 : CActor, actor2 : CActor ) : float { var distance : float; var mpac : CMovingPhysicalAgentComponent; distance = VecDistance2D( actor1.GetWorldPosition(), actor2.GetWorldPosition() ); mpac = (CMovingPhysicalAgentComponent)actor1.GetMovingAgentComponent(); if ( mpac ) { distance -= mpac.GetCapsuleRadius(); } mpac = (CMovingPhysicalAgentComponent)actor2.GetMovingAgentComponent(); if ( mpac ) { distance -= mpac.GetCapsuleRadius(); } return distance; } protected function ProcessSelectionWeights() : STargetSelectionWeights { var selectionWeights : STargetSelectionWeights; if ( ShouldUsePCModeTargeting() ) { selectionWeights.angleWeight = 0.75f; selectionWeights.distanceWeight = 0.25f; selectionWeights.distanceRingWeight = 0.f; return selectionWeights; } if ( IsInCombatAction() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Roll ) ) { selectionWeights.angleWeight = 0.575f; selectionWeights.distanceWeight = 0.175f; selectionWeights.distanceRingWeight = 0.25f; } if ( !lAxisReleasedAfterCounter || IsInCombatAction() ) // !bLAxisReleased || { if ( theInput.GetActionValue( 'ThrowItem' ) == 1.f || ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) ) { selectionWeights.angleWeight = 1.f; selectionWeights.distanceWeight = 0.f; selectionWeights.distanceRingWeight = 0.f; } else if ( !lAxisReleasedAfterCounter ) // !bLAxisReleased ) { selectionWeights.angleWeight = 0.55f;//0.75f; selectionWeights.distanceWeight = 0.45f;//0.25f; selectionWeights.distanceRingWeight = 0.f;//0.3f; } else { selectionWeights.angleWeight = 0.75f; selectionWeights.distanceWeight = 0.25f; selectionWeights.distanceRingWeight = 0.f;//0.3f; } } else if( !IsCurrentSignChanneled() ) { selectionWeights.angleWeight = 0.35f; selectionWeights.distanceWeight = 0.65f; selectionWeights.distanceRingWeight = 0.f; } else { selectionWeights.angleWeight = 0.275f; selectionWeights.distanceWeight = 0.375f; selectionWeights.distanceRingWeight = 0.35f; } return selectionWeights; } protected function CalcSelectionPriority( target : CEntity, selectionWeights : STargetSelectionWeights, sourcePosition : Vector, headingVector : Vector ) : float { var sourceToTarget : Vector; var sourceToTargetDist : float; var sourceToTargetAngleDiff : float; var selectionPriority : float; sourceToTarget = target.GetWorldPosition() - sourcePosition; sourceToTargetDist = VecLength2D( sourceToTarget ); // normalize2D sourcetoTarget if ( sourceToTargetDist < 0.0001f ) { sourceToTarget = Vector( 0.0f, 0.0f, 0.0f ); } else { sourceToTarget *= ( 1.0f / sourceToTargetDist ); } sourceToTargetAngleDiff = AbsF( Rad2Deg( AcosF( VecDot2D( sourceToTarget, headingVector ) ) ) ); selectionPriority = ( selectionWeights.angleWeight * ( ( 180 - sourceToTargetAngleDiff ) / 180 ) ); selectionPriority += selectionWeights.distanceWeight * ( ( softLockDist - sourceToTargetDist ) / softLockDist ); if ( sourceToTargetDist > 0.f && sourceToTargetDist <= 6.f ) { selectionPriority += selectionWeights.distanceRingWeight * 1.0f; } else if ( sourceToTargetDist > 6.f && sourceToTargetDist <= softLockDist ) { selectionPriority += selectionWeights.distanceRingWeight * 0.4f; } return selectionPriority; } protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool ) { var playerToTargetDistance : float; var target : CActor; var allow : bool; target = GetTarget(); if ( !IsInNonGameplayCutscene() ) allow = true; if ( allow ) { if ( targetActor ) { if ( ( targetActor.IsAlive() && !targetActor.IsKnockedUnconscious() ) || finishableEnemiesList.Contains( targetActor ) ) allow = true; else allow = false; } else allow = true; } if ( forceSetTarget ) allow = true; if ( allow && target != targetActor ) allow = true; else allow = false; if ( allow ) { SetPlayerTarget( targetActor ); //playerToTargetDistance = VecDistance( GetWorldPosition(), targetActor.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) ); //LogChannel( 'Targeting', "selection " + playerToTargetDistance ); } } /* protected function SetTarget( targetActor : CActor, optional forceSetTarget : bool ) { var playerToTargetDistance : float; var target : CActor; //var gec : CGameplayEffectsComponent; if ( !IsInNonGameplayCutscene() && ( ( ( !targetActor || ( ( targetActor.IsAlive() || finishableEnemiesList.Contains( targetActor ) ) && !targetActor.IsKnockedUnconscious() ) ) && !IsActorLockedToTarget() ) || forceSetTarget ) ) { target = GetTarget(); if ( target != targetActor ) { if( target ) { target.StopEffect( 'select_character' ); //gec = GetGameplayEffectsComponent( target ); //if(gec) // gec.SetGameplayEffectFlag( EGEF_OutlineTarget, 0 ); } SetPlayerTarget( targetActor ); target = targetActor; if(target) { playerToTargetDistance = VecDistance( GetWorldPosition(), target.GetNearestPointInBothPersonalSpaces( GetWorldPosition() ) ); } //LogChannel( 'Targeting', "selection " + playerToTargetDistance ); } } } */ public function SetSlideTarget( actor : CGameplayEntity ) { //if ( slideTarget != actor && slideTarget ) // EnableCloseCombatCharacterRadius( false ); slideTarget = actor; if ( slideTarget ) SetPlayerCombatTarget((CActor)slideTarget); else Log( "slideTarget = NULL" ); if ( slideTarget == nonActorTarget ) UpdateDisplayTarget( true, true ); else UpdateDisplayTarget(); ConfirmDisplayTargetTimer(0.f); } event OnForceSelectLockTarget() { ForceSelectLockTarget(); } private function ForceSelectLockTarget() { var newMoveTarget : CActor; var target : CActor; newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 90 ); if ( !newMoveTarget ) newMoveTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, -90 ); if ( newMoveTarget ) { thePlayer.ProcessLockTarget( newMoveTarget ); target = GetTarget(); if ( target ) { thePlayer.SetSlideTarget( target ); if ( IsHardLockEnabled() ) thePlayer.HardLockToTarget( true ); } } else { thePlayer.HardLockToTarget( false ); } } public function SetFinisherVictim( actor : CActor ) { finisherVictim = actor; } public function GetFinisherVictim() : CActor { return finisherVictim; } protected function SetNonActorTarget( actor : CGameplayEntity ) { if ( nonActorTarget != actor ) nonActorTarget = actor; } timer function DisableTargetHighlightTimer( time : float , id : int) { var target : CActor; target = GetTarget(); if( target ) { target.StopEffect( 'select_character' ); } } public function WasVisibleInScaledFrame( entity : CEntity, frameSizeX : float, frameSizeY : float ) : bool { var position : Vector; var positionFound : bool; var inFront : bool; var x, y : float; var boneIndex : int; var actor : CActor; var gameplayEntity : CGameplayEntity; var gameplayEntityMatrix : Matrix; var drawableComp : CDrawableComponent; var box : Box; var ok : bool; if ( !entity ) { return false; } if ( frameSizeX <= 0.0f && frameSizeY <= 0.0f ) { LogChannel( 'WasVisibleInScaledFrame', "ERROR: WasVisibleInScaledFrame: frameSizeX && frameSizeY are both negative!!!" ); return false; } if ( useNativeTargeting ) { return targeting.WasVisibleInScaledFrame( entity, frameSizeX, frameSizeY ); } position = entity.GetWorldPosition(); actor = (CActor)entity; if ( actor ) { boneIndex = entity.GetBoneIndex( 'pelvis' ); if ( boneIndex == -1 ) { boneIndex = entity.GetBoneIndex( 'k_pelvis_g' ); // not hack at all. DONE !*100000000000000000000 } if ( boneIndex != -1 ) { position = MatrixGetTranslation( entity.GetBoneWorldMatrixByIndex( boneIndex ) ); } else { position = entity.GetWorldPosition(); position.Z += ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight() * 0.5; } positionFound = true; } else { gameplayEntity = (CGameplayEntity)entity; if ( gameplayEntity && !( gameplayEntity.aimVector.X == 0 && gameplayEntity.aimVector.Y == 0 && gameplayEntity.aimVector.Z == 0 ) ) { gameplayEntityMatrix = gameplayEntity.GetLocalToWorld(); position = VecTransform( gameplayEntityMatrix, gameplayEntity.aimVector ); positionFound = true; } } // if still not found proper position for test if ( !positionFound ) { drawableComp = (CDrawableComponent)entity.GetComponentByClassName( 'CDrawableComponent' ); if ( drawableComp && drawableComp.GetObjectBoundingVolume( box ) ) { position.Z += ( ( box.Max.Z - box.Min.Z ) * 0.66f ); } } inFront = theCamera.WorldVectorToViewRatio( position, x, y ); if ( !inFront ) { return false; } x = AbsF( x ); y = AbsF( y ); ok = true; ok = ok && ( frameSizeX <= 0.0f || x < frameSizeX ); ok = ok && ( frameSizeY <= 0.0f || y < frameSizeY ); return ok; } public function HardLockToTarget( flag : bool ) { EnableHardLock( flag ); LockToTarget( flag ); } public function LockToTarget( flag : bool ) { if ( IsHardLockEnabled() && !flag ) return; LockCameraToTarget( flag ); LockActorToTarget( flag ); } public function LockCameraToTarget( flag : bool ) { if ( flag && !IsCameraLockedToTarget() ) { thePlayer.EnableManualCameraControl( false, 'LockCameraToTarget' ); //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( false ); SetIsCameraLockedToTarget( flag ); } else if ( !flag && IsCameraLockedToTarget() ) { thePlayer.EnableManualCameraControl( true, 'LockCameraToTarget' ); //((CCustomCamera)theCamera.GetTopmostCameraObject()).EnableManualControl( true ); SetIsCameraLockedToTarget( flag ); } } public function LockActorToTarget( flag : bool, optional withoutIcon : bool ) { var displayTargetActor : CActor; if ( flag ) { if ( !IsActorLockedToTarget() ) { //SetSlideTarget( target ); SetIsActorLockedToTarget( flag ); SetMoveTargetChangeAllowed( true ); SetMoveTarget( GetTarget() ); SetMoveTargetChangeAllowed( false ); SetTarget( GetTarget() ); SetSlideTarget( GetTarget() ); AddTimer( 'CheckLockTargetIsAlive', 0.5, true ); } if ( IsActorLockedToTarget() ) { displayTargetActor = (CActor)( GetDisplayTarget() ); if ( displayTargetActor && IsThreat( displayTargetActor ) && !withoutIcon ) EnableHardLockIcon( flag ); } } else if ( !flag && IsActorLockedToTarget() ) { SetIsActorLockedToTarget( flag ); SetMoveTargetChangeAllowed( true ); RemoveTimer( 'CheckLockTargetIsAlive' ); EnableHardLockIcon( flag ); } } private function EnableHardLockIcon( flag : bool ) { var hud : CR4ScriptedHud; var module : CR4HudModuleEnemyFocus; if( GetTarget().HasTag( 'NoHardLockIcon' ) ) return; hud = (CR4ScriptedHud)theGame.GetHud(); module = (CR4HudModuleEnemyFocus)hud.GetHudModule("EnemyFocusModule"); module.SetShowHardLock( flag ); } private timer function CheckLockTargetIsAlive( time : float , id : int) { var vitality : float; var essence : float; var actor : CActor; var target : CActor; target = (CActor)GetDisplayTarget(); if( !target || !target.IsAlive() || ( !target.GetGameplayVisibility() ) || !CanBeTargetedIfSwimming( target ) || (!target.UsesVitality() && !target.UsesEssence())) { if ( !ProcessLockTarget() ) HardLockToTarget( false ); } } ////////////////////////////////////////////////////////////////////////////////////////// // // @Damage // ////////////////////////////////////////////////////////////////////////////////////////// protected function PlayHitAnimation(damageAction : W3DamageAction, animType : EHitReactionType) { var hitRotation : float; if( damageAction.HasAnyCriticalEffect() ) return; if( !substateManager.ReactOnBeingHit() && !IsUsingVehicle() ) { return; } if ( damageAction.GetHitReactionType() == EHRT_Reflect ) SetBehaviorVariable( 'isAttackReflected', 1.f ); else SetBehaviorVariable( 'isAttackReflected', 0.f ); SetBehaviorVariable( 'HitReactionType',(int)animType); SetBehaviorVariable( 'HitReactionWeapon', ProcessSwordOrFistHitReaction( this, (CActor)damageAction.attacker ) ); if (damageAction.attacker) { SetHitReactionDirection(damageAction.attacker); SetDetailedHitReaction(damageAction.GetSwingType(), damageAction.GetSwingDirection()); } RaiseForceEvent( 'Hit' ); if ( IsUsingBoat() ) { SoundEvent("cmb_play_hit_light"); return; } if ( IsUsingVehicle() ) return; if(damageAction.attacker) { hitRotation = VecHeading( damageAction.attacker.GetWorldPosition() - GetWorldPosition() ); if ( this.GetBehaviorVariable( 'HitReactionDirection' ) == (float)( (int)EHRD_Back ) ) hitRotation += 180.f; //GetVisualDebug().AddArrow( 'temp', GetWorldPosition(), GetWorldPosition() + VecFromHeading( hitRotation )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f ); SetCustomRotation( 'Hit', hitRotation, 1080.f, 0.1f, false ); } CriticalEffectAnimationInterrupted("PlayHitAnimation"); } public function ReduceDamage( out damageData : W3DamageAction) { super.ReduceDamage(damageData); //halve damage if from your own bomb if(damageData.attacker == this && (damageData.GetBuffSourceName() == "petard" || (W3Petard)damageData.causer) ) { if ( theGame.CanLog() ) { LogDMHits("CR4Player.ReduceDamage: hitting self with own bomb - damage reduced by 50%", damageData ); } damageData.processedDmg.vitalityDamage = damageData.processedDmg.vitalityDamage / 2; damageData.processedDmg.essenceDamage = damageData.processedDmg.essenceDamage / 2; } } //crit hit chance 0-1 public function GetCriticalHitChance(isHeavyAttack : bool, target : CActor, victimMonsterCategory : EMonsterCategory) : float { var critChance : float; var oilChanceAttribute : name; critChance = 0; //cheats if(FactsQuerySum('debug_fact_critical_boy') > 0) { critChance += 1; } if( IsInState( 'HorseRiding' ) && ((CActor)GetUsedVehicle()).GetMovingAgentComponent().GetRelativeMoveSpeed() >= 4.0 ) { critChance += 1; } //normal case critChance += CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_CHANCE)); //active skills bonus if(isHeavyAttack && CanUseSkill(S_Sword_s08)) critChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s08, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s08); else if (!isHeavyAttack && CanUseSkill(S_Sword_s17)) critChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s17, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s17); if(target && target.HasBuff(EET_Confusion)) { critChance += ((W3ConfuseEffect)target.GetBuff(EET_Confusion)).GetCriticalHitChanceBonus(); } //oils oilChanceAttribute = MonsterCategoryToCriticalChanceBonus(victimMonsterCategory); if(IsNameValid(oilChanceAttribute)) critChance += CalculateAttributeValue(GetAttributeValue(oilChanceAttribute)); return critChance; } //gets damage bonus for critical hit public function GetCriticalHitDamageBonus(weaponId : SItemUniqueId, victimMonsterCategory : EMonsterCategory, isStrikeAtBack : bool) : SAbilityAttributeValue { var bonus, oilBonus : SAbilityAttributeValue; var vsAttributeName : name; bonus = super.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, isStrikeAtBack); //oil bonus if(inv.ItemHasOilApplied(weaponId)) { vsAttributeName = MonsterCategoryToCriticalDamageBonus(victimMonsterCategory); oilBonus = inv.GetItemAttributeValue(weaponId, vsAttributeName); bonus += oilBonus; } return bonus; } /** Called when we want to play hit animation */ public function ReactToBeingHit(damageAction : W3DamageAction, optional buffNotApplied : bool) : bool { var strength : float; var animType : EHitReactionType; var sup : bool; var boat : CBoatComponent; var combatActionType : int; var attackAction : W3Action_Attack; var npc : CNewNPC; var shakeCam : bool; attackAction = (W3Action_Attack)damageAction; //not parried, not countered, not dot, not dodged if(!damageAction.IsDoTDamage() && (!attackAction || (!attackAction.IsParried() && !attackAction.IsCountered() && !attackAction.WasDodged()) ) ) { npc = (CNewNPC)attackAction.attacker; if(npc && npc.IsHeavyAttack(attackAction.GetAttackName())) theGame.VibrateControllerVeryHard();//player got heavy hit else theGame.VibrateControllerHard();//player got hit } if ( (CActor)GetUsedVehicle() && this.playerAiming.GetCurrentStateName() == 'Aiming' ) { OnRangedForceHolster( true, true ); } combatActionType = (int)GetBehaviorVariable( 'combatActionType' ); if ( thePlayer.IsCurrentlyDodging() && ( combatActionType == (int)CAT_Roll || combatActionType == (int)CAT_CiriDodge ) ) sup = false; else if ( this.GetCurrentStateName() == 'DismountHorse' ) sup = false; else sup = super.ReactToBeingHit(damageAction, buffNotApplied); sup = false; //telemetry if(damageAction.attacker) theTelemetry.LogWithLabelAndValue( TE_FIGHT_HERO_GETS_HIT, damageAction.attacker.ToString(), (int)damageAction.processedDmg.vitalityDamage ); //camera shake if(damageAction.DealsAnyDamage()) { if( ((W3PlayerWitcher)this) && GetWitcherPlayer().IsAnyQuenActive() && damageAction.IsDoTDamage()) { shakeCam = false; } else { shakeCam = true; } if(shakeCam) { animType = ModifyHitSeverityReaction(this, damageAction.GetHitReactionType()); if(animType == EHRT_Light || animType == EHRT_LightClose) strength = 0.1; else if(animType == EHRT_Heavy || animType == EHRT_Igni) strength = 0.2; GCameraShakeLight(strength, false, GetWorldPosition(), 10.0); } this.HitReactionEffect( 0.25 ); //reset uninterrupted hits ResetUninterruptedHitsCount(); } //pause health regen if(!damageAction.IsDoTDamage() && IsThreatened() && ShouldPauseHealthRegenOnHit() && damageAction.DealsAnyDamage() && !damageAction.WasDodged() && attackAction.CanBeParried() && !attackAction.IsParried()) { PauseHPRegenEffects('being_hit', theGame.params.ON_HIT_HP_REGEN_DELAY); } //if player is on a boat and not moving then force dismount /*if(usedVehicle) { boat = (CBoatComponent) usedVehicle.GetComponentByClassName('CBoatComponent'); if(boat && boat.GetLinearVelocityXY() < boat.IDLE_SPEED_THRESHOLD) { boat.StopAndDismountBoat(); } }*/ //finesse achievement fail if(damageAction.processedDmg.vitalityDamage > 0 && !((W3Effect_Toxicity)damageAction.causer)) ReceivedCombatDamage(); //tutorial if(FactsQuerySum("tut_fight_use_slomo") > 0) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) ); FactsRemove("tut_fight_slomo_ON"); } // State if( !substateManager.ReactOnBeingHit( damageAction ) ) { GoToCombatIfNeeded(); //PushState( 'CombatFists' ); } return sup; } protected function ShouldPauseHealthRegenOnHit() : bool { return true; } public function PlayHitEffect(damageAction : W3DamageAction) { super.PlayHitEffect(damageAction); //fullscreen hit fx if(damageAction.DealsAnyDamage() && !damageAction.IsDoTDamage()) PlayEffect('hit_screen'); } function HitReactionEffect( interval : float ) { if ( hitReactionEffect ) { PlayEffect( 'radial_blur' ); hitReactionEffect = false; } else { AddTimer( 'HitReactionEffectCooldown', interval, false ); } } timer function HitReactionEffectCooldown( td : float , id : int) { hitReactionEffect = true; } ////////////////////////////////////////////////////////////////////////////////////////// // // @Parry // ////////////////////////////////////////////////////////////////////////////////////////// function PerformParryCheck( parryInfo : SParryInfo) : bool { var mult : float; var parryType : EParryType; var parryDir : EPlayerParryDirection; var parryHeading : float; var fistFightParry : bool; var action : W3DamageAction; var xmlStaminaDamage : float; var xmlStaminaDamageName : name = 'stamina_damage' ; // if ( !parryInfo.canBeParried ) // return false; if(CanParryAttack() && /*parryInfo.targetToAttackerAngleAbs < theGame.params.PARRY_HALF_ANGLE &&*/ FistFightCheck( parryInfo.target, parryInfo.attacker, fistFightParry ) ) { parryHeading = GetParryHeading( parryInfo, parryDir ) ; //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetParryHeading( parryInfo, parryDir ) )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f ); SetBehaviorVariable( 'parryDirection', (float)( (int)( parryDir ) ) ); SetBehaviorVariable( 'parryDirectionOverlay', (float)( (int)( parryDir ) ) ); SetBehaviorVariable( 'parryType', ChooseParryTypeIndex( parryInfo ) ); if ( IsInCombatActionFriendly() ) RaiseEvent('CombatActionFriendlyEnd'); if ( HasStaminaToParry(parryInfo.attackActionName) ) { this.SetBehaviorVariable( 'combatActionType', (int)CAT_Parry ); if ( parryInfo.targetToAttackerDist > 3.f && !bLAxisReleased && !thePlayer.IsCiri() ) { if ( !RaiseForceEvent( 'PerformParryOverlay' ) ) return false; else ClearCustomOrientationInfoStack(); } else { if ( RaiseForceEvent( 'PerformParry' ) ) { OnCombatActionStart(); ClearCustomOrientationInfoStack(); SetSlideTarget( parryInfo.attacker ); SetCustomRotation( 'Parry', parryHeading, 1080.f, 0.1f, false ); } else return false; } } else { AddEffectDefault(EET_Stagger, parryInfo.attacker, "Parry"); return true; } //parryTarget := this if ( parryInfo.attacker.IsWeaponHeld( 'fist' ) && !parryInfo.target.IsWeaponHeld( 'fist' ) ) { parryInfo.attacker.ReactToReflectedAttack(parryInfo.target); } else { if ( this.IsInFistFightMiniGame() && fistFightParry ) { if ( IsNameValid(xmlStaminaDamageName) ) { xmlStaminaDamage = CalculateAttributeValue(parryInfo.attacker.GetAttributeValue( xmlStaminaDamageName )); DrainStamina(ESAT_FixedValue, xmlStaminaDamage); } } else { DrainStamina(ESAT_Parry, 0, 0, '', 0, mult); } if(IsLightAttack(parryInfo.attackActionName)) parryInfo.target.PlayEffectOnHeldWeapon('light_block'); else parryInfo.target.PlayEffectOnHeldWeapon('heavy_block'); } return true; } return false; } protected function GetParryHeading( parryInfo : SParryInfo, out parryDir : EPlayerParryDirection ) : float { var targetToAttackerHeading : float; var currToTargetAttackerAngleDiff : float; targetToAttackerHeading = VecHeading( parryInfo.attacker.GetWorldPosition() - parryInfo.target.GetWorldPosition() ); currToTargetAttackerAngleDiff = AngleDistance( VecHeading( parryInfo.target.GetHeadingVector() ), targetToAttackerHeading ); if ( !parryInfo.target.IsWeaponHeld( 'fist' ) ) { if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 ) { parryDir = PPD_Forward; return targetToAttackerHeading; } else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 135 ) { parryDir = PPD_Right; //return targetToAttackerHeading; return targetToAttackerHeading + 90; } else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff > -135 ) { parryDir = PPD_Left; //return targetToAttackerHeading; return targetToAttackerHeading - 90; } else { parryDir = PPD_Back; //return targetToAttackerHeading; return targetToAttackerHeading + 180; } } else { if( currToTargetAttackerAngleDiff > -45 && currToTargetAttackerAngleDiff < 45 ) { parryDir = PPD_Forward; return targetToAttackerHeading; } else if( currToTargetAttackerAngleDiff >= 45 && currToTargetAttackerAngleDiff < 180 ) { parryDir = PPD_Right; return targetToAttackerHeading + 90; } else if( currToTargetAttackerAngleDiff <= -45 && currToTargetAttackerAngleDiff >= -180 ) { parryDir = PPD_Left; return targetToAttackerHeading - 90; } else { parryDir = PPD_Back; return targetToAttackerHeading + 180; } } } function ProcessLockTarget( optional newLockTarget : CActor, optional checkLeftStickHeading : bool ) : bool { var attackerNearestPoint : Vector; var playerNearestPoint : Vector; var incomingAttacker : CActor; var tempLockTarget : CActor; var target : CActor; var useIncomingAttacker : bool; if ( newLockTarget ) tempLockTarget = newLockTarget; else { incomingAttacker = GetClosestIncomingAttacker(); if ( incomingAttacker && incomingAttacker.IsAlive() && IsUsingVehicle() ) { tempLockTarget = incomingAttacker; useIncomingAttacker = false; } if ( !useIncomingAttacker ) { target = GetTarget(); if ( target && target.IsAlive() && target.GetGameplayVisibility() && IsEnemyVisible( target ) && IsThreat( target ) && CanBeTargetedIfSwimming( target ) ) tempLockTarget = FindTarget(); else { tempLockTarget = GetScreenSpaceLockTarget( GetDisplayTarget(), 180.f, 1.f, 0.f ); } } } if ( tempLockTarget ) { if ( IsCombatMusicEnabled() || hostileEnemies.Size() > 0 ) { if ( !IsThreat( tempLockTarget ) ) tempLockTarget = NULL; } } SetTarget( tempLockTarget, true ); SetMoveTargetChangeAllowed( true ); SetMoveTarget( tempLockTarget ); SetMoveTargetChangeAllowed( false ); SetSlideTarget( tempLockTarget ); if ( tempLockTarget ) { if ( this.IsActorLockedToTarget() ) EnableHardLockIcon( true ); return true; } else return false; } ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// @COMBAT /////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// //checks if player is doing special attack light/heavy public function IsDoingSpecialAttack(heavy : bool) : bool { var pat : EPlayerAttackType; if(IsInCombatAction() && ( (int)GetBehaviorVariable('combatActionType')) == CAT_SpecialAttack) { pat = (int)GetBehaviorVariable('playerAttackType'); if(heavy && pat == PAT_Heavy) { return true; } else if(!heavy && pat == PAT_Light) { return true; } } return false; } public function SetIsCurrentlyDodging(enable : bool, optional isRolling : bool) { super.SetIsCurrentlyDodging(enable, isRolling); if ( isRolling ) { SetCanPlayHitAnim( false ); this.AddBuffImmunity( EET_KnockdownTypeApplicator, 'Roll', false ); this.AddBuffImmunity( EET_Knockdown, 'Roll', false ); this.AddBuffImmunity( EET_HeavyKnockdown, 'Roll', false ); this.AddBuffImmunity( EET_Stagger, 'Roll', false ); } else { SetCanPlayHitAnim( true ); this.RemoveBuffImmunity( EET_KnockdownTypeApplicator, 'Roll' ); this.RemoveBuffImmunity( EET_Knockdown, 'Roll' ); this.RemoveBuffImmunity( EET_HeavyKnockdown, 'Roll' ); this.RemoveBuffImmunity( EET_Stagger, 'Roll' ); } } public function EnableHardLock( flag : bool ) { super.EnableHardLock(flag); if(flag && ShouldProcessTutorial('TutorialTargettingWaiting')) { FactsAdd("tut_hardlocked"); } } protected function TestParryAndCounter(data : CPreAttackEventData, weaponId : SItemUniqueId, out parried : bool, out countered : bool) : array { var ret : array; //cheat for QA tests - NPCs won't parry/counter if(FactsQuerySum('player_is_the_boss') > 0) { //---------------- DEBUG //draw debug AR SetDebugAttackRange(data.rangeName); RemoveTimer('PostAttackDebugRangeClear'); //disable AR clearing since we've just set a new one return ret; } ret = super.TestParryAndCounter(data, weaponId, parried, countered); //achievement if(parried) theGame.GetGamerProfile().ResetStat(ES_CounterattackChain); return ret; } public function SetSpecialAttackTimeRatio(f : float) { LogSpecialHeavy(f); specialAttackTimeRatio = f; } public function GetSpecialAttackTimeRatio() : float { return specialAttackTimeRatio; } //called when we processed special heavy attack action - either from hit or from CombatActionEnd() public function OnSpecialAttackHeavyActionProcess() { //clear ration after attack performed SetSpecialAttackTimeRatio(0.f); } protected function DoAttack(animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array, attackAnimationName : name, hitTime : float) { var shakeStr : float; var weapon : EPlayerWeapon; var targetActor : CActor; //cam shake for player's heavy attacks /* if ( animData.attackName == 'attack_heavy_special' ) { if( specialAttackTimeRatio != 1 ) shakeStr = (specialAttackTimeRatio / 3.333) + 0.2; else shakeStr = 0.5; GCameraShake( shakeStr, false, GetWorldPosition(), 10); } else if ( IsHeavyAttack(attackActionName) ) { if(parriedBy.Size() > 0) shakeStr = 0.2; else shakeStr = 0.1; GCameraShake(shakeStr, false, GetWorldPosition(), 10); } */ // modXTfinishers END targetActor = (CActor)slideTarget; if ( targetActor && hitTargets.Contains(targetActor) ) { weapon = this.GetMostConvenientMeleeWeapon(targetActor,true); if ( this.GetCurrentMeleeWeaponType() != PW_Fists && weapon != this.GetCurrentMeleeWeaponType() ) { if ( weapon == PW_Steel ) { thePlayer.OnEquipMeleeWeapon(PW_Steel,true); } else if ( weapon == PW_Silver ) { thePlayer.OnEquipMeleeWeapon(PW_Silver,true); } } } super.DoAttack(animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime); } //var delayCombatStanceTimeStamp : float; private var confirmCombatStanceTimeStamp : float; private var isConfirmingCombatStance : bool; final function SetPlayerCombatStance(stance : EPlayerCombatStance, optional force : bool ) { var stanceInt : int; if ( !CanChangeCombatStance( stance, force ) ) return; combatStance = stance; stanceInt = (int)stance; SetBehaviorVariable( 'playerCombatStance' , (float)stanceInt); SetBehaviorVariable( 'playerCombatStanceForOverlay' , (float)stanceInt); if ( force ) SetBehaviorVariable( 'forceCombatStance' , 1.f); else SetBehaviorVariable( 'forceCombatStance' , 0.f); } private function CanChangeCombatStance( stance : EPlayerCombatStance, optional force : bool ) : bool { var currTime : float; if ( force ) return true; if ( IsInFistFightMiniGame() ) return true; if ( isInHolsterAnim ) return false; if ( ( combatStance == PCS_Normal || combatStance == PCS_AlertFar ) && stance == PCS_AlertNear ) { currTime = theGame.GetEngineTimeAsSeconds(); if ( !isConfirmingCombatStance ) { isConfirmingCombatStance = true; confirmCombatStanceTimeStamp = currTime; if ( this.playerMoveType == PMT_Idle ) this.SetBehaviorVariable('isInCombatForOverlay',0.f); else this.SetBehaviorVariable('isInCombatForOverlay',1.f); return false; } else if ( currTime < confirmCombatStanceTimeStamp + 1.f ) { if ( stance == PCS_AlertNear ) return false; } else isConfirmingCombatStance = false; } else isConfirmingCombatStance = false; return true; } private var isInHolsterAnim : bool; event OnHolsterWeaponStart() { isInHolsterAnim = true; } event OnHolsterWeaponEnd() { isInHolsterAnim = false; } final function GetPlayerCombatStance() : EPlayerCombatStance { return combatStance; } timer function DelayedDisableFindTarget( time : float , id : int) { if ( GetTarget().IsAlive() ) { EnableFindTarget( false ); } else { EnableFindTarget( true ); } } /////////////////////////////////////////////////////////////////////////// // @BUFFER @COMBATACTIONBUFFER /////////////////////////////////////////////////////////////////////////// private var dodgeTimerRunning : bool; function StartDodgeTimer() { dodgeTimerRunning = true; thePlayer.AddTimer('DodgeTimer',0.2,false); } function StopDodgeTimer() { this.RemoveTimer('DodgeTimer'); dodgeTimerRunning = false; } function IsDodgeTimerRunning() : bool { return dodgeTimerRunning; } timer function DodgeTimer( dt : float, id : int ) { dodgeTimerRunning = false; } public function EvadePressed( bufferAction : EBufferActionType ) { } public function PerformingCombatAction() : EBufferActionType { return BufferCombatAction; } public function PushCombatActionOnBuffer( action : EBufferActionType, stage : EButtonStage, optional allSteps : bool ) { BufferButtonStage = stage; BufferCombatAction = action; BufferAllSteps = allSteps; } protected function ProcessCombatActionHeading( action : EBufferActionType ) : float { var processedActionHeading : float; HandleMovement( 0.f ); if ( ShouldUsePCModeTargeting() ) return theGame.GetGameCamera().GetHeading(); if ( lAxisReleasedAfterCounter ) // && IsInCombatAction() ) ResetCachedRawPlayerHeading(); processedActionHeading = cachedRawPlayerHeading; return processedActionHeading; } /* private function ProcessCombatActionHeading( action : EBufferActionType ) : float { var processedActionHeading : float; var unusedActor : CActor; //MS: placeholder variable to fix memory error if ( IsUsingVehicle() ) { processedActionHeading = theGame.GetGameCamera().GetHeading(); return processedActionHeading; } if ( !bLAxisReleased || lAxisPushedTimeStamp + 0.5f > theGame.GetEngineTimeAsSeconds() ) processedActionHeading = cachedRawPlayerHeading; else { if ( GetDisplayTarget() ) { if ( cachedCombatActionHeading == cachedRawPlayerHeading ) ResetCachedRawPlayerHeading(); else { cachedRawPlayerHeading = cachedCombatActionHeading; canResetCachedCombatActionHeading = true; } processedActionHeading = cachedRawPlayerHeading; } else { if ( lAxisReleasedAfterCounterNoCA ) ResetRawPlayerHeading(); cachedRawPlayerHeading = rawPlayerHeading; if ( lAxisReleasedAfterCounterNoCA ) processedActionHeading = GetHeading(); else processedActionHeading = cachedRawPlayerHeading; } } if ( this.IsCameraLockedToTarget() && this.IsActorLockedToTarget() && action != EBAT_Dodge && action != EBAT_Roll ) processedActionHeading = theGame.GetGameCamera().GetHeading(); if ( lAxisReleasedAfterCounterNoCA ) { if ( action == EBAT_Dodge || action == EBAT_Roll ) { if ( ( !IsEnemyInCone( this, GetHeadingVector(), softLockDist, 60.f, unusedActor ) || !IsEnemyInCone( this, GetHeadingVector() + 180, softLockDist, 60.f, unusedActor ) ) && moveTarget ) processedActionHeading = VecHeading( moveTarget.GetWorldPosition() - GetWorldPosition() ) + 180; else processedActionHeading = GetHeading() + 180; } } //GetVisualDebug().AddArrow( 'cachedRawPlayerHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( cachedRawPlayerHeading ), 1.f, 0.2f, 0.2f, true, Color(0,255,128), true, 5.f ); //GetVisualDebug().AddArrow( 'CombatActionHeading', GetWorldPosition(), GetWorldPosition() + VecFromHeading( GetCombatActionHeading() )*2, 1.f, 0.2f, 0.2f, true, Color(0,255,255), true, 5.f ); return processedActionHeading; }*/ function ResetRawPlayerHeading() { if ( GetDisplayTarget() ) rawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ); else rawPlayerHeading = GetHeading(); //LogChannel('ResetRawPlayerHeading',"ResetRawPlayerHeading" ); } function ResetCachedRawPlayerHeading() { cachedRawPlayerHeading = rawPlayerHeading; if ( GetDisplayTarget() && IsDisplayTargetTargetable() && AbsF( AngleDistance( VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ), this.GetHeading() ) ) < 90.f ) cachedRawPlayerHeading = VecHeading( GetDisplayTarget().GetWorldPosition() - this.GetWorldPosition() ); else cachedRawPlayerHeading = this.GetHeading(); if ( canResetCachedCombatActionHeading ) cachedCombatActionHeading = cachedRawPlayerHeading; } public function GetCombatActionTarget( action : EBufferActionType ) : CGameplayEntity { var selectedTargetableEntity : CGameplayEntity; if ( !this.IsUsingVehicle() ) selectedTargetableEntity = FindNonActorTarget( true, action ); if ( selectedTargetableEntity ) { return selectedTargetableEntity; } else { /*if ( !IsCombatMusicEnabled() && displayTarget ) { if ( !( (CActor)displayTarget ) ) return NULL; else return displayTarget; }*/ if ( !this.IsUsingVehicle() ) FindTarget( true, action, true ); else ((CR4PlayerStateUseGenericVehicle)this.GetState( 'UseGenericVehicle' )).FindTarget(); return GetTarget(); } } //MS: FindNonActorTarget may or may not have an interaction component, which is why it is separate from ProcessInteraction private function FindNonActorTarget( actionCheck : bool, optional action : EBufferActionType ) : CGameplayEntity { var targetableEntities : array; var selectedTargetableEntity : CGameplayEntity; var selectionPriority : array< float >; var selectionWeights : STargetSelectionWeights; var findEntityDist : float; var i, size : int; var playerHeading : float; var playerInventory : CInventoryComponent; var castSignType : ESignType; var targetingInfo : STargetingInfo; var playerPosition : Vector; var cameraPosition : Vector; var playerHeadingVector : Vector; var rawPlayerHeadingVector : Vector; playerPosition = this.GetWorldPosition(); cameraPosition = theCamera.GetCameraPosition(); rawPlayerHeadingVector = VecFromHeading( rawPlayerHeading ); if ( bCanFindTarget && !IsHardLockEnabled() ) { if ( actionCheck && IsInCombat() && action == EBAT_CastSign ) { findEntityDist = 6.f; selectionWeights.angleWeight = 0.375f; selectionWeights.distanceWeight = 0.275f; selectionWeights.distanceRingWeight = 0.35f; } else if ( !IsInCombat() && lastAxisInputIsMovement ) { findEntityDist = softLockDist; selectionWeights.angleWeight = 0.375f; selectionWeights.distanceWeight = 0.275f; selectionWeights.distanceRingWeight = 0.35f; } else { findEntityDist = softLockDist; selectionWeights.angleWeight = 0.75f; selectionWeights.distanceWeight = 0.125f; selectionWeights.distanceRingWeight = 0.125f; } //MSTODO : Ask programmers for filter for interactive entities if ( !IsInCombat() || !bLAxisReleased ) { FindGameplayEntitiesInRange( targetableEntities, this, findEntityDist, 10, theGame.params.TAG_SOFT_LOCK ); } if ( targetableEntities.Size() > 0 ) { playerInventory = this.GetInventory(); castSignType = this.GetEquippedSign(); if ( !bLAxisReleased ) { targetingInfo.source = this; targetingInfo.canBeTargetedCheck = false; targetingInfo.coneCheck = true; targetingInfo.coneHalfAngleCos = 0.5f; // = CosF( Deg2Rad( 120.0f * 0.5f ) ) targetingInfo.coneDist = softLockDist; targetingInfo.coneHeadingVector = rawPlayerHeadingVector; targetingInfo.distCheck = true; targetingInfo.invisibleCheck = false; targetingInfo.navMeshCheck = false; targetingInfo.frameScaleX = 1.0f; targetingInfo.frameScaleY = 1.0f; targetingInfo.knockDownCheck = false; targetingInfo.knockDownCheckDist = 0.0f; targetingInfo.rsHeadingCheck = false; targetingInfo.rsHeadingLimitCos = 1.0f; } for( i = targetableEntities.Size()-1; i>=0; i-=1 ) { if ( bLAxisReleased ) { if ( !lastAxisInputIsMovement ) { if ( !WasVisibleInScaledFrame( targetableEntities[i], 0.9f, 0.9f ) ) { targetableEntities.Erase(i); continue; } } else if ( !WasVisibleInScaledFrame( targetableEntities[i], 1.f, 1.f ) ) { targetableEntities.Erase(i); continue; } } else { targetingInfo.targetEntity = targetableEntities[i]; if ( actionCheck && moveTarget ) { targetingInfo.inFrameCheck = false; if ( !IsEntityTargetable( targetingInfo ) ) { targetableEntities.Erase(i); continue; } } else { targetingInfo.inFrameCheck = true; if ( !IsEntityTargetable( targetingInfo ) ) { targetableEntities.Erase(i); continue; } } } if ( actionCheck ) { if ( action == EBAT_ItemUse ) { if ( ( playerInventory.IsItemBomb( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bomb' ) ) || ( playerInventory.IsItemCrossbow( this.GetSelectedItemId() ) && !targetableEntities[i].HasTag( 'softLock_Bolt' ) ) ) { targetableEntities.Erase(i); continue; } } else if ( action == EBAT_CastSign ) { if ( ( castSignType == ST_Aard && !targetableEntities[i].HasTag( 'softLock_Aard' ) ) || ( castSignType == ST_Igni && !targetableEntities[i].HasTag( 'softLock_Igni' ) ) || ( castSignType == ST_Axii && !targetableEntities[i].HasTag( 'softLock_Axii' ) ) || castSignType == ST_Yrden || castSignType == ST_Quen ) { targetableEntities.Erase(i); continue; } } else if ( action == EBAT_LightAttack || action == EBAT_HeavyAttack || action == EBAT_SpecialAttack_Heavy ) { if ( ( IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Fist' ) ) || ( !IsWeaponHeld( 'fist' ) && !targetableEntities[i].HasTag( 'softLock_Weapon' ) ) ) { targetableEntities.Erase(i); continue; } } else { targetableEntities.Erase(i); continue; } } } } if ( targetableEntities.Size() > 0) { playerHeading = this.GetHeading(); playerHeadingVector = this.GetHeadingVector(); if ( IsInCombat() ) { for( i = 0; i < targetableEntities.Size(); i += 1 ) { if ( bLAxisReleased ) selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) ); else selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) ); } if ( selectionPriority.Size() > 0 ) selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ]; } else { if ( bLAxisReleased ) { if ( !lastAxisInputIsMovement ) { for( i = 0; i < targetableEntities.Size(); i += 1 ) selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, cameraPosition, rawPlayerHeadingVector ) ); if ( selectionPriority.Size() > 0 ) selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ]; } else { if ( IsInCombatAction() ) selectedTargetableEntity = nonActorTarget; else { for( i = 0; i < targetableEntities.Size(); i += 1 ) selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, playerHeadingVector ) ); if ( selectionPriority.Size() > 0 ) { selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ]; targetingInfo.source = this; targetingInfo.targetEntity = selectedTargetableEntity; targetingInfo.canBeTargetedCheck = false; targetingInfo.coneCheck = true; targetingInfo.coneHalfAngleCos = 0.0f; // = CosF( Deg2Rad( 180.0f * 0.5f ) ) targetingInfo.coneDist = softLockDist; targetingInfo.coneHeadingVector = this.GetHeadingVector(); targetingInfo.distCheck = true; targetingInfo.invisibleCheck = false; targetingInfo.navMeshCheck = false; targetingInfo.inFrameCheck = false; targetingInfo.frameScaleX = 1.0f; targetingInfo.frameScaleY = 1.0f; targetingInfo.knockDownCheck = false; targetingInfo.knockDownCheckDist = 0.0f; targetingInfo.rsHeadingCheck = false; targetingInfo.rsHeadingLimitCos = 1.0f; if ( !IsEntityTargetable( targetingInfo ) ) selectedTargetableEntity = NULL; } } } } else { for( i = 0; i < targetableEntities.Size(); i += 1 ) selectionPriority.PushBack( CalcSelectionPriority( targetableEntities[i], selectionWeights, playerPosition, rawPlayerHeadingVector ) ); if ( selectionPriority.Size() > 0 ) selectedTargetableEntity = targetableEntities[ ArrayFindMaxF( selectionPriority ) ]; } } } else selectedTargetableEntity = NULL; } SetNonActorTarget( selectedTargetableEntity ); return selectedTargetableEntity; } /* timer function IsItemUseInputHeld ( time : float , id : int) { if ( GetBIsInputAllowed() && GetBIsCombatActionAllowed() && IsActionAllowed( EIAB_Crossbow ) && inv.IsIdValid( GetSelectedItemId() ) && inv.IsItemCrossbow( GetSelectedItemId()En ) && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' ) { SetIsAimingCrossbow( true ); PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed ); ProcessCombatActionBuffer(); } if ( theInput.GetActionValue( 'ThrowItem' ) == 0.f ) { if ( GetBIsCombatActionAllowed() ) { PushCombatActionOnBuffer( EBAT_ItemUse, BS_Pressed ); ProcessCombatActionBuffer(); } SetIsAimingCrossbow( false ); RemoveTimer( 'IsItemUseInputHeld' ); } }*/ public function SetupCombatAction( action : EBufferActionType, stage : EButtonStage ) { var weaponType : EPlayerWeapon; var canAttackTarget : CGameplayEntity; var target : CActor; /*if( thePlayer.substateManager.GetStateCur() == 'Slide' ) { return; }*/ if ( !IsCombatMusicEnabled() ) { SetCombatActionHeading( ProcessCombatActionHeading( action ) ); FindTarget(); UpdateDisplayTarget( true ); } if ( displayTarget && IsDisplayTargetTargetable() ) canAttackTarget = displayTarget; else if ( GetTarget() ) canAttackTarget = GetTarget(); else if( !target && IsCombatMusicEnabled() ) canAttackTarget = moveTarget; target = (CActor)canAttackTarget; if ( !AllowAttack( target, action ) ) return; if( ( action != EBAT_ItemUse ) && ( action != EBAT_CastSign ) ) { weaponType = weaponHolster.GetCurrentMeleeWeapon(); PrepareToAttack( target, action ); //Do not automatically attack when drawing sword if ( weaponType != weaponHolster.GetCurrentMeleeWeapon() ) { //Check if switching from PW_None to PW_Fists. If so, allow the attack if ( !( weaponType == PW_None && weaponHolster.GetCurrentMeleeWeapon() == PW_Fists ) ) return; } } //geralt's special attack heavy if(action == EBAT_SpecialAttack_Heavy && !((W3ReplacerCiri)this) ) thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02)); CriticalEffectAnimationInterrupted("SetupCombatAction " + action); PushCombatActionOnBuffer( action, stage ); if( GetBIsCombatActionAllowed() ) { ProcessCombatActionBuffer(); } } public function AllowAttack( target : CActor, action : EBufferActionType ) : bool { var newTarget : CActor; var canAttackWhenNotInCombat : bool; var messageDisplayed : bool; var itemId : SItemUniqueId; var isShootingCrossbow : bool; var isInCorrectState : bool; if ( target ) { if ( target.IsTargetableByPlayer()) { if ( !target.IsAttackableByPlayer() ) { DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_cant_attack_this_target")); return false; } } } if ( this.GetCurrentStateName() == 'Exploration' ) isInCorrectState = true; if ( action == EBAT_ItemUse ) { itemId = thePlayer.GetSelectedItemId(); if ( inv.IsIdValid(itemId) && inv.IsItemCrossbow(itemId) ) isShootingCrossbow = true; if ( !isInCorrectState ) { if ( this.GetCurrentStateName() == 'AimThrow' && !isShootingCrossbow ) { isInCorrectState = true; } } } if ( isInCorrectState ) canAttackWhenNotInCombat = thePlayer.CanAttackWhenNotInCombat( action, false, newTarget, target ); if( !target ) { if ( isInCorrectState ) { SetCombatActionHeading( ProcessCombatActionHeading( action ) ); target = newTarget; } } if ( isInCorrectState ) { if ( !canAttackWhenNotInCombat ) { if ( DisplayCannotAttackMessage( target ) ) messageDisplayed = true; else if ( ( action == EBAT_LightAttack || action == EBAT_HeavyAttack ) && !RaiseAttackFriendlyEvent( target ) ) messageDisplayed = true; else { if ( !CanRaiseCombatActionFriendlyEvent( isShootingCrossbow ) ) messageDisplayed = true; } } if ( messageDisplayed ) { theInput.ForceDeactivateAction('ThrowItem'); theInput.ForceDeactivateAction('ThrowItemHold'); return false; } } return true; } //returns true if processed public function ProcessCombatActionBuffer() : bool { var actionResult : bool; var action : EBufferActionType = this.BufferCombatAction; var stage : EButtonStage = this.BufferButtonStage; var s : SNotWorkingOutFunctionParametersHackStruct1; var allSteps : bool = this.BufferAllSteps; if ( IsInCombatActionFriendly() ) { RaiseEvent('CombatActionFriendlyEnd'); } //Disable any npcs that are set to unpushable when Player performs another combat action if ( ( action != EBAT_SpecialAttack_Heavy && action != EBAT_ItemUse ) || ( action == EBAT_SpecialAttack_Heavy && stage == BS_Pressed ) || ( action == EBAT_ItemUse && stage != BS_Released ) ) { GetMovingAgentComponent().GetMovementAdjustor().CancelAll(); SetUnpushableTarget( NULL ); } //if ( !( action == EBAT_Dodge && stage == BS_Pressed && IsInCombatAction() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Dodge ) ) if ( !( action == EBAT_Dodge || action == EBAT_Roll ) ) SetIsCurrentlyDodging(false); //-- init SetCombatActionHeading( ProcessCombatActionHeading( action ) ); //theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation(); if ( action == EBAT_ItemUse && GetInventory().IsItemCrossbow( selectedItemId ) ) { //stage == BS_Pressed && if ( rangedWeapon && ( ( rangedWeapon.GetCurrentStateName() != 'State_WeaponShoot' && rangedWeapon.GetCurrentStateName() != 'State_WeaponAim' ) || GetIsShootingFriendly() ) ) { SetSlideTarget( GetCombatActionTarget( action ) ); } } else if ( !( ( action == EBAT_SpecialAttack_Heavy && stage == BS_Released ) || GetCurrentStateName() == 'AimThrow' ) ) { SetSlideTarget( GetCombatActionTarget( action ) ); } if( !slideTarget ) LogChannel( 'Targeting', "NO SLIDE TARGET" ); //-- process actionResult = true; switch ( action ) { case EBAT_EMPTY : { this.BufferAllSteps = false; return true; } break; case EBAT_LightAttack : { if ( IsCiri() ) return false; switch ( stage ) { case BS_Pressed ://BS_Released : { // early out, stamina drain etc //if( HasStaminaToUseAction(ESAT_LightAttack) ) //{ // replacing stamina lock with stamina drain - change in design /* s = LockStamina(ESAT_LightAttack); if(s.retValue) { AddCombatActionStaminaLock(s.outValue); } */ DrainStamina(ESAT_LightAttack); //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack ); thePlayer.BreakPheromoneEffect(); actionResult = OnPerformAttack(theGame.params.ATTACK_NAME_LIGHT); //} } break; default : { actionResult = false; }break; } }break; case EBAT_HeavyAttack : { if ( IsCiri() ) return false; switch ( stage ) { case BS_Released : { // early out, stamina drain etc //if( HasStaminaToUseAction(ESAT_HeavyAttack) ) //{ // replacing stamina lock with stamina drain - change in design /* s = LockStamina(ESAT_HeavyAttack); if(s.retValue) { AddCombatActionStaminaLock(s.outValue); } */ DrainStamina(ESAT_HeavyAttack); //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack ); thePlayer.BreakPheromoneEffect(); actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY); //} } break; case BS_Pressed : { if ( this.GetCurrentStateName() == 'CombatFists' ) { // early out, stamina drain etc //if( HasStaminaToUseAction(ESAT_HeavyAttack) ) //{ // replacing stamina lock with stamina drain - change in design /* s = LockStamina(ESAT_HeavyAttack); if(s.retValue) { AddCombatActionStaminaLock(s.outValue); } */ DrainStamina(ESAT_HeavyAttack); //target.SignalGameplayEventParamInt('Time2Dodge', (int)EDT_Attack ); thePlayer.BreakPheromoneEffect(); actionResult = this.OnPerformAttack(theGame.params.ATTACK_NAME_HEAVY); //} } } break; default : { actionResult = false; } break; } } break; case EBAT_ItemUse : //this gets called only for bombs. No usable items use this! { switch ( stage ) { case BS_Pressed : { if ( !( (W3PlayerWitcher)this ) || ( !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) ) //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) ) { if ( inv.IsItemCrossbow( selectedItemId ) ) { rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) ); rangedWeapon.OnRangedWeaponPress(); GetTarget().SignalGameplayEvent( 'Approach' ); } else if(inv.IsItemBomb(selectedItemId) && this.inv.SingletonItemGetAmmo(selectedItemId) > 0 ) { BombThrowStart(); GetTarget().SignalGameplayEvent( 'Approach' ); } else { DrainStamina(ESAT_UsableItem); UsableItemStart(); } } } if (!allSteps) break; case BS_Released: { if ( !( (W3PlayerWitcher)this ) || ( !IsInCombatActionFriendly() && ( GetBIsCombatActionAllowed() || !( !GetBIsCombatActionAllowed() && ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack || GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) ) ) ) ) //( !IsCastingSign() && !IsInCombatActionFriendly() && !( !GetBIsCombatActionAllowed() && GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) ) ) { if ( inv.IsItemCrossbow( selectedItemId ) ) { /*if ( rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' ) { rangedWeapon = ( Crossbow )( inv.GetItemEntityUnsafe( selectedItemId ) ); rangedWeapon.OnRangedWeaponPress(); }*/ rangedWeapon.OnRangedWeaponRelease(); } else if(inv.IsItemBomb(selectedItemId)) { BombThrowRelease(); } else { UsableItemRelease(); } } } break; default : { actionResult = false; break; } } } break; case EBAT_Dodge : { switch ( stage ) { case BS_Released : { theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 ); thePlayer.BreakPheromoneEffect(); actionResult = this.OnPerformEvade( PET_Dodge ); } break; /*case BS_Pressed : { actionResult = this.OnPerformEvade( PET_Roll ); } break;*/ default : { actionResult = false; } break; } } break; case EBAT_Roll : { if ( IsCiri() ) return false; switch ( stage ) { case BS_Released : { theGame.GetBehTreeReactionManager().CreateReactionEvent( this, 'PlayerEvade', 1.0f, 10.0f, -1.0f, -1 ); thePlayer.BreakPheromoneEffect(); actionResult = this.OnPerformEvade( PET_Roll ); } break; case BS_Pressed : { if ( this.GetBehaviorVariable( 'combatActionType' ) == 2.f ) { if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' ) actionResult = this.OnPerformEvade( PET_Pirouette ); else actionResult = this.OnPerformEvade( PET_Roll ); } else { if ( GetCurrentStateName() == 'CombatSteel' || GetCurrentStateName() == 'CombatSilver' ) { actionResult = this.OnPerformEvade( PET_Dodge ); actionResult = this.OnPerformEvade( PET_Pirouette ); } else { actionResult = this.OnPerformEvade( PET_Dodge ); actionResult = this.OnPerformEvade( PET_Roll ); } } } break; default : { actionResult = false; } break; } } break; case EBAT_Draw_Steel : { switch ( stage ) { case BS_Pressed : { if( !IsActionAllowed(EIAB_DrawWeapon) ) { thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon); actionResult = false; break; } if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) ) { OnEquipMeleeWeapon( PW_Steel, false, true ); } actionResult = false; } break; default : { actionResult = false; } break; } } break; case EBAT_Draw_Silver : { switch ( stage ) { case BS_Pressed : { if( !IsActionAllowed(EIAB_DrawWeapon) ) { thePlayer.DisplayActionDisallowedHudMessage(EIAB_DrawWeapon); actionResult = false; break; } if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) ) { OnEquipMeleeWeapon( PW_Silver, false, true ); } actionResult = false; } break; default : { actionResult = false; } break; } } break; case EBAT_Sheathe_Sword : { switch ( stage ) { case BS_Pressed : { if( GetCurrentMeleeWeaponType() == PW_Silver ) { if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'silversword' ) ) { OnEquipMeleeWeapon( PW_Silver, false, true ); } } else if( GetCurrentMeleeWeaponType() == PW_Steel ) { if( GetWitcherPlayer().IsItemEquippedByCategoryName( 'steelsword' ) ) { OnEquipMeleeWeapon( PW_Steel, false, true ); } } actionResult = false; } break; default : { actionResult = false; } break; } } break; default: return false; //not processed } //if here then buffer was processed CleanCombatActionBuffer(); if (actionResult) { SetCombatAction( action ) ; if(GetWitcherPlayer().IsInFrenzy()) GetWitcherPlayer().SkillFrenzyFinish(0); } return true; } public function CleanCombatActionBuffer() { BufferCombatAction = EBAT_EMPTY; BufferAllSteps = false; } public function CancelHoldAttacks() { thePlayer.RemoveTimer( 'IsSpecialLightAttackInputHeld' ); thePlayer.RemoveTimer( 'IsSpecialHeavyAttackInputHeld' ); thePlayer.RemoveTimer( 'SpecialAttackLightSustainCost' ); thePlayer.RemoveTimer( 'SpecialAttackHeavySustainCost' ); thePlayer.RemoveTimer( 'UpdateSpecialAttackLightHeading' ); thePlayer.UnblockAction( EIAB_Crossbow, 'SpecialAttack' ); if ( thePlayer.GetBehaviorVariable( 'combatActionType' ) == (int)CAT_SpecialAttack ) { if( thePlayer.GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Light && thePlayer.GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f ) { thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s01)); thePlayer.PushCombatActionOnBuffer( EBAT_SpecialAttack_Light, BS_Released ); thePlayer.ProcessCombatActionBuffer(); //thePlayer.SetupCombatAction( EBAT_SpecialAttack_Light, BS_Released ); ((W3PlayerWitcherStateCombatFists) GetState('Combat')).ResetTimeToEndCombat(); } else if( thePlayer.GetBehaviorVariable( 'playerAttackType' ) == (int)PAT_Heavy && thePlayer.GetBehaviorVariable( 'isPerformingSpecialAttack' ) == 1.f ) { thePlayer.SetAttackActionName(SkillEnumToName(S_Sword_s02)); thePlayer.PushCombatActionOnBuffer( EBAT_SpecialAttack_Heavy, BS_Released ); thePlayer.ProcessCombatActionBuffer(); //thePlayer.SetupCombatAction( EBAT_SpecialAttack_Heavy, BS_Released ); } } } public function RaiseAttackFriendlyEvent( actor : CActor ) : bool { var playerToTargetHeading : float; if ( actor && RaiseCombatActionFriendlyEvent() ) { SetBehaviorVariable( 'tauntTypeForOverlay', 0.f ); SetBehaviorVariable( 'combatActionTypeForOverlay', (int)CAT_Attack ); if ( actor ) actor.SignalGameplayEvent('PersonalTauntAction'); theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'TauntAction', -1.0, 4.5f, -1, 9999, true ); //reactionSystemSearch OnCombatActionStart(); playerToTargetHeading = VecHeading( actor.GetWorldPosition() - GetWorldPosition() ); SetCustomRotation( 'Attack', playerToTargetHeading, 0.0f, 0.3f, false ); return true; } return false; } public function SendAttackReactionEvent() { var reactionName : name; /*switch ( action ) { case EBAT_LightAttack : reactionName = 'AttackAction'; break; case EBAT_HeavyAttack : reactionName = 'AttackAction'; break; case EBAT_SpecialAttack_Light : reactionName = 'AttackAction'; break; case EBAT_SpecialAttack_Heavy : reactionName = 'AttackAction'; break; case EBAT_Ciri_SpecialAttack : reactionName = 'AttackAction'; break; default: return; }*/ reactionName = 'AttackAction'; if ( IsNameValid(reactionName) ) { theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, reactionName, -1.0, 8.0f, -1, 5, true ); //reactionSystemSearch } // event for horse - trigger running away theGame.GetBehTreeReactionManager().CreateReactionEventIfPossible( this, 'outOfMyWay', -1.0, 2.0f, -1, 5, true ); //reactionSystemSearch } var forceCanAttackWhenNotInCombat : int; // 0 = NoForce, 1 = ForceWhenNoDisplayTarget 2 = ForceEvenWithDisplayTarget public function SetForceCanAttackWhenNotInCombat( forceMode : int ) { forceCanAttackWhenNotInCombat = forceMode; } public function CanAttackWhenNotInCombat( actionType : EBufferActionType, altCast : bool, out newTarget : CActor, optional target : CGameplayEntity ) : bool { var localTargets : array; var i, size : int; var inputHeading : float; var clearanceMin, clearanceMax : float; var attackLength : float; var attackAngle : float; var npc : CNewNPC; var canAttackTarget : CGameplayEntity; var canAttackTargetActor : CActor; if ( target ) canAttackTarget = target; else if ( displayTarget && IsDisplayTargetTargetable() ) canAttackTarget = displayTarget; else canAttackTarget = slideTarget; canAttackTargetActor = (CActor)canAttackTarget; if ( forceCanAttackWhenNotInCombat == 2 ) return true; else if ( forceCanAttackWhenNotInCombat == 1 && ( !canAttackTarget || !canAttackTargetActor.IsHuman() ) ) return true; if ( actionType == EBAT_CastSign ) { if ( thePlayer.GetEquippedSign() != ST_Quen && thePlayer.GetEquippedSign() != ST_Axii ) { if ( CanUseSkill( S_Magic_s20 ) ) { if ( thePlayer.GetEquippedSign() == ST_Aard ) attackLength = 6.f; else if ( thePlayer.GetEquippedSign() == ST_Igni ) attackLength = 4.f; else attackLength = 6.f; } else { if ( thePlayer.GetEquippedSign() == ST_Aard ) attackLength = 9.f; else if ( thePlayer.GetEquippedSign() == ST_Igni ) attackLength = 6.f; else attackLength = 6.f; } if ( altCast ) attackAngle = 180.f; else // sign cone angle / 2 with a bonus for safetey attackAngle = 90.f; if ( !lastAxisInputIsMovement ) inputHeading = VecHeading( theCamera.GetCameraDirection() ); else if ( lAxisReleasedAfterCounter ) inputHeading = GetHeading(); else inputHeading = GetCombatActionHeading(); clearanceMin = 1.f; clearanceMax = attackLength + 1.f; } else if ( thePlayer.GetEquippedSign() == ST_Axii ) { npc = (CNewNPC)canAttackTarget; if ( npc && npc.GetNPCType() == ENGT_Quest && !npc.HasTag(theGame.params.TAG_AXIIABLE_LOWER_CASE) && !npc.HasTag(theGame.params.TAG_AXIIABLE)) return false; else if ( npc && npc.IsUsingHorse() ) return false; else return true; } else return true; } else if ( actionType == EBAT_ItemUse ) { attackLength = theGame.params.MAX_THROW_RANGE; attackAngle = 90.f; if ( thePlayer.lastAxisInputIsMovement ) inputHeading = GetCombatActionHeading(); else inputHeading = VecHeading( theCamera.GetCameraDirection() ); clearanceMin = 0.8f; clearanceMax = attackLength + 3.f; } else { if ( actionType == EBAT_SpecialAttack_Light || actionType == EBAT_SpecialAttack_Heavy ) { attackLength = 1.9f; attackAngle = 90.f; } else { if( thePlayer.GetCurrentMeleeWeaponType() == PW_Fists || thePlayer.GetCurrentMeleeWeaponType() == PW_None ) attackLength = 1.2f; else attackLength = 1.9f; attackAngle = 90.f; } if ( lastAxisInputIsMovement ) inputHeading = GetCombatActionHeading(); else inputHeading = VecHeading( theCamera.GetCameraDirection() ); clearanceMin = attackLength / 2.f; clearanceMax = attackLength + 3.f; } //Use slideTarget first if it's NULL, then we try other npcs in the area if ( canAttackTarget ) { if ( ( canAttackTargetActor && canAttackTargetActor.IsHuman() ) || canAttackTargetActor.HasTag( 'softLock_Friendly' ) ) { if ( ShouldPerformFriendlyAction( canAttackTargetActor, inputHeading, attackAngle, clearanceMin, clearanceMax ) ) { SetSlideTarget( canAttackTargetActor ); newTarget = canAttackTargetActor; return false; } } //return true; } return true; thePlayer.GetVisibleEnemies( localTargets ); size = localTargets.Size(); if ( size > 0 ) { for ( i = size-1; i>=0; i-=1 ) { /* Andrzej: Geralt's friendly combat action - taunting actors with a sword or playing with Signs is set to work only for humans. We don't want it to work against all non-humans, so I've added an exception that works similar to targeting non actor objects. If you want Geralt to play friendly combat action when targeting monsters, add tag softLock_Friendly to monster's entity. */ if ( !localTargets[i].IsHuman() && !localTargets[i].HasTag( 'softLock_Friendly' ) ) localTargets.Erase(i); } } size = localTargets.Size(); if ( size > 0 ) { for ( i = 0; i < localTargets.Size(); i += 1 ) { if ( ShouldPerformFriendlyAction( localTargets[i], inputHeading, attackAngle, clearanceMin, clearanceMax ) ) { SetSlideTarget( localTargets[i] ); newTarget = localTargets[i]; return false; } } } newTarget = NULL; return true; } private function ShouldPerformFriendlyAction( actor : CActor, inputHeading, attackAngle, clearanceMin, clearanceMax : float ) : bool { var npc : CNewNPC; var argh : float; var playerToTargetDist : float; npc = (CNewNPC)actor; if ( npc && ( GetAttitudeBetween(thePlayer, npc) == AIA_Hostile || ( GetAttitudeBetween(thePlayer, npc) == AIA_Neutral && npc.GetNPCType() != ENGT_Guard ) ) ) { } else { playerToTargetDist = VecDistance( this.GetWorldPosition(), actor.PredictWorldPosition( 0.5f ) ); //actor.GetNearestPointInPersonalSpace( this.GetWorldPosition() ) ); argh = AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) ); if ( AbsF( AngleDistance( inputHeading, VecHeading( actor.GetWorldPosition() - thePlayer.GetWorldPosition() ) ) ) < attackAngle ) { if ( playerToTargetDist < clearanceMax ) { return true; } } else { if ( playerToTargetDist < clearanceMin ) { return true; } } } return false; } /////////////////////////////////////////////////////////////////////////// // HUD //#B /////////////////////////////////////////////////////////////////////////// public function GetHudMessagesSize() : int { return HudMessages.Size(); } public function GetHudPendingMessage() : string { return HudMessages[0]; } public function DisplayHudMessage( value : string ) : void { if (value == "") { return; } if( GetHudMessagesSize() > 0 ) { if( HudMessages[HudMessages.Size()-1] == value ) { return; } } HudMessages.PushBack(value); } //hacks for review requests private final function DisallowedActionDontShowHack(action : EInputActionBlock) : bool { var locks : array< SInputActionLock >; var i : int; //no info if we're trying to attack while staggered if((action == EIAB_Fists || action == EIAB_SwordAttack || action == EIAB_Signs || action == EIAB_LightAttacks || action == EIAB_HeavyAttacks || action == EIAB_SpecialAttackLight || action == EIAB_SpecialAttackHeavy) && (HasBuff(EET_Stagger) || HasBuff(EET_LongStagger)) ) { return true; } //always show meditation message if(action == EIAB_OpenMeditation) return false; //if there's at least one lock from quest or from location fine locks = GetActionLocks(action); for(i=0; i { if(locks[i].isFromQuest || locks[i].isFromPlace) return false; } if ( this.IsCurrentlyUsingItemL() ) { if ( action == EIAB_HeavyAttacks || action == EIAB_Parry ) return false; } //otherwise we don't display locks return true; } public final function DisplayActionDisallowedHudMessage(action : EInputActionBlock, optional isCombatLock : bool, optional isPlaceLock : bool, optional isTimeLock : bool, optional isDangerous : bool) { var lockType : name; if(action != EIAB_Undefined && DisallowedActionDontShowHack(action)) return; //combat lock is strongest - overrides all if(IsInCombat() && !IsActionCombat(action)) isCombatLock = true; //if no specific lock set, check based on action if(!isCombatLock && !isPlaceLock && ! isTimeLock && action != EIAB_Undefined) { lockType = inputHandler.GetActionBlockedHudLockType(action); if(lockType == 'combat') isCombatLock = true; else if(lockType == 'place') isPlaceLock = true; else if(lockType == 'time') isTimeLock = true; } if(isDangerous) { DisplayHudMessage(GetLocStringByKeyExt( "message_meditation_too_dangerous" )); } else if(isCombatLock) { DisplayHudMessage(GetLocStringByKeyExt( "panel_hud_message_actionnotallowed_combat" )); } else if(isPlaceLock) { DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_here" )); } else if(isTimeLock) { DisplayHudMessage(GetLocStringByKeyExt( "menu_cannot_perform_action_now" )); } } //removes first or all instances of given message public function RemoveHudMessageByString(msg : string, optional allQueuedInstances : bool) { var i, j : int; for(i=0; i { if(HudMessages[i] == msg) { HudMessages.EraseFast(i); if(!allQueuedInstances) return; break; } } //if here then we want all remaining instances as well for(j=HudMessages.Size()-1; j >= i; j-=1) { if(HudMessages[i] == msg) { HudMessages.EraseFast(i); } } } public function RemoveHudMessageByIndex(idx : int) { if(idx >= 0 && idx < HudMessages.Size()) HudMessages.Erase(idx); } function SetSettlementBlockCanter( valueAdd : int ) // #B { m_SettlementBlockCanter += valueAdd; } var countDownToStart : int; default countDownToStart = 0; function DisplayRaceStart( countDownSecondsNumber : int ) // #B { var i : int; countDownToStart = countDownSecondsNumber; for( i = countDownSecondsNumber; i > 0; i -= 1 ) { DisplayHudMessage(IntToString(i)); } DisplayHudMessage(GetLocStringByKeyExt("panel_hud_message_race_start")); AddTimer('RaceCountdown',1,true); } timer function RaceCountdown(dt : float, id : int) // #B { var hud : CR4ScriptedHud; var messageModule : CR4HudModuleMessage; countDownToStart -= 1; hud = (CR4ScriptedHud)theGame.GetHud(); if( hud ) { messageModule = (CR4HudModuleMessage)hud.GetHudModule("MessageModule"); if( messageModule ) { messageModule.OnMessageHidden(); // to force show next messeage } } if( countDownToStart <= 0 ) { RemoveTimer('RaceCountdown'); } } public function GetCountDownToStart() : int // #B { return countDownToStart; } public function HAXE3GetContainer() : W3Container //#B temp for E3 { return HAXE3Container; } public function HAXE3SetContainer( container : W3Container) : void //#B temp for E3 { HAXE3Container = container; } public function HAXE3GetAutoLoot() : bool //#B temp for E3 { return HAXE3bAutoLoot; } public function HAXE3SetAutoLoot( value : bool ) : void //#B temp for E3 { HAXE3bAutoLoot = value; } public function GetShowHud() : bool { return bShowHud; } public function SetShowHud( value : bool ) : void { bShowHud = value; } public function DisplayItemRewardNotification( itemName : name, optional quantity : int ) : void { var hud : CR4ScriptedHud; hud = (CR4ScriptedHud)theGame.GetHud(); hud.OnItemRecivedDuringScene(itemName, quantity); // #B because our default currency are Crowns !!! } function IsNewQuest( questGuid : CGUID ) : bool // #B { var i : int; for(i = 0; i < displayedQuestsGUID.Size(); i += 1 ) { if( displayedQuestsGUID[i] == questGuid ) { return false; } } displayedQuestsGUID.PushBack(questGuid); return true; } function GetRewardMultiplier( rewardName : name ) : float // #B { var i : int; for(i = 0; i < rewardsMultiplier.Size(); i += 1 ) { if( rewardsMultiplier[i].rewardName == rewardName ) { return rewardsMultiplier[i].rewardMultiplier; } } return 1.0; } function GetRewardMultiplierExists( rewardName : name ) : bool // #B { var i : int; for(i = 0; i < rewardsMultiplier.Size(); i += 1 ) { if( rewardsMultiplier[i].rewardName == rewardName ) { return true; } } return false; } function SetRewardMultiplier( rewardName : name, value : float ) : void // #B { var i : int; var rewardMultiplier : SRewardMultiplier; for(i = 0; i < rewardsMultiplier.Size(); i += 1 ) { if( rewardsMultiplier[i].rewardName == rewardName ) { rewardsMultiplier[i].rewardMultiplier = value; return; } } rewardMultiplier.rewardName = rewardName; rewardMultiplier.rewardMultiplier = value; rewardsMultiplier.PushBack(rewardMultiplier); } function RemoveRewardMultiplier( rewardName : name ) : void // #B { var i : int; for(i = 0; i < rewardsMultiplier.Size(); i += 1 ) { if( rewardsMultiplier[i].rewardName == rewardName ) { rewardsMultiplier.Erase(i); return; } } } //////////////////////////////////////////////////////////////////////////////// /////////////////////////// @OILS //////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// public final function GetCurrentOilAmmo(id : SItemUniqueId) : int { return inv.GetItemModifierInt(id, 'oil_charges'); } public final function GetMaxOilAmmo(id : SItemUniqueId) : int { return inv.GetItemModifierInt(id, 'oil_max_charges'); } public final function ReduceOilAmmo(id : SItemUniqueId, optional ammo : int) { var currentAmmo : int; if(ammo == 0) ammo = 1; currentAmmo = GetCurrentOilAmmo(id); if(currentAmmo > 0) { currentAmmo = Max(currentAmmo - ammo, 0); inv.SetItemModifierInt(id, 'oil_charges', currentAmmo); if(currentAmmo == 0) { RemoveItemOil(id); //count alchemy usage but only after nightmare if(ShouldProcessTutorial('TutorialAlchemyRefill') && FactsQuerySum("q001_nightmare_ended") > 0 && GetWitcherPlayer()) FactsAdd('tut_alch_refill', 1); } } theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied ); } //removes oil from given item public function RemoveItemOil(id : SItemUniqueId) { var i : int; var dm : CDefinitionsManagerAccessor; var abilities : array; var sword : CWitcherSword; dm = theGame.GetDefinitionsManager(); inv.GetItemAbilities(id, abilities); for(i=0; i if(dm.AbilityHasTag(abilities[i], theGame.params.OIL_ABILITY_TAG)) inv.RemoveItemCraftedAbility(id, abilities[i]); inv.SetItemModifierInt(id, 'oil_charges', -1); inv.SetItemModifierInt(id, 'oil_max_charges', -1); sword = (CWitcherSword) inv.GetItemEntityUnsafe(id); sword.RemoveOil( inv ); theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied ); } //////////////////////////////////////////////////////////////////////////////// // // @Items // //////////////////////////////////////////////////////////////////////////////// public final function HasRequiredLevelToEquipItem(item : SItemUniqueId) : bool { //No witcher gear lvl ++ else if(inv.GetItemQuality(item) == 5){} // No witcher gear lvl -- return true; } public function SkillReduceBombAmmoBonus() { var i, ammo, maxAmmo : int; var items : array; items = inv.GetSingletonItems(); for(i=0; i { ammo = inv.GetItemModifierInt(items[i], 'ammo_current'); //if doesn't have infinite ammo if(ammo > 0) { maxAmmo = inv.SingletonItemGetMaxAmmo(items[i]); //if current ammo > max ammo, set current ammo to max ammo if(ammo > maxAmmo) { inv.SetItemModifierInt(items[i], 'ammo_current', maxAmmo); } } } theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnAmmoChanged ); } public function ConsumeItem( itemId : SItemUniqueId ) : bool { var params : SCustomEffectParams; var buffs : array; var i : int; var category : name; var potionToxicity : float; if(!inv.IsIdValid(itemId)) return false; //apply buff category = inv.GetItemCategory(itemId); if(category == 'edibles' || inv.ItemHasTag(itemId, 'Drinks') || ( category == 'alchemy_ingredient' && inv.ItemHasTag(itemId, 'Alcohol')) ) { //cannot eat in fistfights if(IsFistFightMinigameEnabled()) { DisplayActionDisallowedHudMessage(EIAB_Undefined, false, false, true); return false; } //edible buff inv.GetItemBuffs(itemId, buffs); for(i=0; i { params.effectType = buffs[i].effectType; params.creator = this; params.sourceName = "edible"; params.customAbilityName = buffs[i].effectAbilityName; AddEffectCustom(params); } //custom hack if ( inv.ItemHasTag(itemId, 'Alcohol') ) { potionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(itemId, 'toxicity')); abilityManager.GainStat(BCS_Toxicity, potionToxicity ); AddEffectDefault(EET_Drunkenness, NULL, inv.GetItemName(itemId)); } PlayItemConsumeSound( itemId ); } if(inv.IsItemFood(itemId)) FactsAdd("consumed_food_cnt"); //remove item if(!inv.ItemHasTag(itemId, theGame.params.TAG_INFINITE_USE) && !inv.RemoveItem(itemId)) { LogAssert(false,"Failed to remove consumable item from player inventory!" + inv.GetItemName( itemId ) ); return false; } return true; } public function MountVehicle( vehicleEntity : CEntity, mountType : EVehicleMountType, optional vehicleSlot : EVehicleSlot ) { var vehicle : CVehicleComponent; vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent')); if ( vehicle ) vehicle.Mount( this, mountType, vehicleSlot ); } public function DismountVehicle( vehicleEntity : CEntity, dismountType : EDismountType ) { var vehicle : CVehicleComponent; vehicle = (CVehicleComponent)(vehicleEntity.GetComponentByClassName('CVehicleComponent')); if ( vehicle ) vehicle.IssueCommandToDismount( dismountType ); } //////////////// // @stamina @stats //////////////// //Returns true if actor has enough stamina to perform given action type (refer to DrainStamina for more info). //If there is not enough stamina and actor is a player character then a insufficient stamina indication is shown on HUD public function HasStaminaToUseAction(action : EStaminaActionType, optional abilityName : name, optional dt :float, optional multiplier : float) : bool { var cost : float; var ret : bool; ret = super.HasStaminaToUseAction(action, abilityName, dt, multiplier); if(!ret) { SetCombatActionHeading( GetHeading() ); if(multiplier == 0) multiplier = 1; cost = multiplier * GetStaminaActionCost(action, abilityName, dt); SetShowToLowStaminaIndication(cost); } return ret; } //since we cannot add timer on abilityManager... timer function AbilityManager_FloorStaminaSegment(dt : float, id : int) { ((W3PlayerAbilityManager)abilityManager).FloorStaminaSegment(); } public function DrainToxicity(amount : float ) { if(abilityManager && abilityManager.IsInitialized() && IsAlive()) abilityManager.DrainToxicity(amount); } public function DrainFocus(amount : float ) { if(abilityManager && abilityManager.IsInitialized() && IsAlive()) abilityManager.DrainFocus(amount); } public function GetOffenseStat():int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetOffenseStat(); return 0; } public function GetDefenseStat():int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetDefenseStat(); return 0; } public function GetSignsStat():float { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSignsStat(); return 0; } //////////////// // water //////////////// private var inWaterTrigger : bool; event OnOceanTriggerEnter() { inWaterTrigger = true; } event OnOceanTriggerLeave() { inWaterTrigger = false; } public function IsInWaterTrigger() : bool { return inWaterTrigger; } ////////////////////////////////////////////////////////////////////////////////////////// // @Skills @Perks ////////////////////////////////////////////////////////////////////////////////////////// public function GetSkillColor(skill : ESkill) : ESkillColor { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillColor(skill); return SC_None; } public function GetSkillSlotIndexFromSkill(skill : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndexFromSkill(skill); return -1; } public final function GetSkillSlotIndex(slotID : int, checkIfUnlocked : bool) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIndex(slotID, checkIfUnlocked); return -1; } public final function GetSkillSlotIDFromIndex(skillSlotIndex : int) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotIDFromIndex(skillSlotIndex); return -1; } public function GetSkillSlotID(skill : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotID(skill); return -1; } public function GetSkillGroupBonus(groupID : int) : name { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetGroupBonus(groupID); return ''; } public function GetGroupBonusCount(commonColor : ESkillColor,groupID : int) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetGroupBonusCount(commonColor, groupID); return 0; } public function GetMutagenSlotIDFromGroupID(groupID : int) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetMutagenSlotIDFromGroupID(groupID); return -1; } public function GetSkillLevel(skill : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillLevel(skill); return -1; } public function GetBoughtSkillLevel(skill : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetBoughtSkillLevel(skill); return -1; } public function AddSkill(skill : ESkill, optional isTemporary : bool) { if(abilityManager && abilityManager.IsInitialized()) ((W3PlayerAbilityManager)abilityManager).AddSkill(skill, isTemporary); } public function AddMultipleSkills(skill : ESkill, optional number : int, optional isTemporary : bool) { var i : int; if(number) { for( i=0; i { AddSkill(skill,isTemporary); } } else { AddSkill(skill,isTemporary); } } public function GetSkillAbilityName(skill : ESkill) : name { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillAbilityName(skill); return ''; } public function HasStaminaToUseSkill(skill : ESkill, optional perSec : bool, optional signHack : bool) : bool { var ret : bool; var cost : float; cost = GetSkillStaminaUseCost(skill, perSec); ret = ( CanUseSkill(skill) && (abilityManager.GetStat(BCS_Stamina, signHack) >= cost) ); //perk, using adrenaline instead of stamina when out of stamina if(!ret && IsSkillSign(skill) && CanUseSkill(S_Perk_09) && GetStat(BCS_Focus) >= 1) ret = true; if(!ret) { SetCombatActionHeading( GetHeading() ); SetShowToLowStaminaIndication(cost); } return ret; } protected function GetSkillStaminaUseCost(skill : ESkill, optional perSec : bool) : float { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillStaminaUseCost(skill, perSec); return 0; } //works for perks and bookperks as well public function GetSkillAttributeValue(skill : ESkill, attributeName : name, addBaseCharAttribute : bool, addSkillModsAttribute : bool) : SAbilityAttributeValue { var null : SAbilityAttributeValue; if(abilityManager && abilityManager.IsInitialized()) return abilityManager.GetSkillAttributeValue(SkillEnumToName(skill), attributeName, addBaseCharAttribute, addSkillModsAttribute); return null; } public function GetSkillLocalisationKeyName(skill : ESkill) : string // #B { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyName(skill); return ""; } public function GetSkillLocalisationKeyDescription(skill : ESkill) : string // #B { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillLocalisationKeyDescription(skill); return ""; } public function GetSkillIconPath(skill : ESkill) : string // #B { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillIconPath(skill); return ""; } public function HasLearnedSkill(skill : ESkill) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).HasLearnedSkill(skill); return false; } public function IsSkillEquipped(skill : ESkill) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).IsSkillEquipped(skill); return false; } public function CanUseSkill(skill : ESkill) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).CanUseSkill(skill); return false; } public function CanLearnSkill(skill : ESkill) : bool //#B { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).CanLearnSkill(skill); return false; } public function HasSpentEnoughPoints(skill : ESkill) : bool //#J { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).HasSpentEnoughPoints(skill); return false; } public function PathPointsForSkillsPath(skill : ESkill) : int //#J { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).PathPointsSpentInSkillPathOfSkill(skill); return -1; } public function GetPlayerSkills() : array // #B { var null : array; if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkills(); return null; } public function GetPlayerSkill(s : ESkill) : SSkill // #B { var null : SSkill; if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkill(s); return null; } public function GetSkillSubPathType(s : ESkill) : ESkillSubPath // #B { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSubPathType(s); return ESSP_NotSet; } public function GetSkillSlotsCount() : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount(); return 0; } public function GetSkillSlots() : array { var null : array; if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillSlots(); return null; } public function GetPlayerSkillMutagens() : array { var null : array; if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetPlayerSkillMutagens(); return null; } // mutagens //public function OnSkillMutagenEquipped() public function BlockSkill(skill : ESkill, block : bool, optional cooldown : float) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).BlockSkill(skill, block, cooldown); return false; } public function IsSkillBlocked(skill : ESkill) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).IsSkillBlocked(skill); return false; } //returns true if succeeded public function EquipSkill(skill : ESkill, slotID : int) : bool { var ret : bool; var groupID : int; var pam : W3PlayerAbilityManager; if(abilityManager && abilityManager.IsInitialized()) { pam = (W3PlayerAbilityManager)abilityManager; ret = pam.EquipSkill(skill, slotID); if(ret) { groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID); LogSkillColors("Equipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> to group <<" + groupID + ">>"); LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>"); LogSkillColors(""); } return ret; } return false; } //returns true if succeeded public function UnequipSkill(slotID : int) : bool { var ret : bool; var groupID : int; var skill : ESkill; var pam : W3PlayerAbilityManager; if(abilityManager && abilityManager.IsInitialized()) { pam = (W3PlayerAbilityManager)abilityManager; GetSkillOnSlot(slotID, skill); ret = pam.UnequipSkill(slotID); if(ret) { groupID = pam.GetSkillGroupIdFromSkillSlotId(slotID); LogSkillColors("Unequipped <<" + GetSkillColor(skill) + ">> skill <<" + skill + ">> from group <<" + groupID + ">>"); LogSkillColors("Group bonus color is now <<" + pam.GetSkillGroupColor(groupID) + ">>"); LogSkillColors(""); } return ret; } return false; } //returns true if succeeded public function GetSkillOnSlot(slotID : int, out skill : ESkill) : bool { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetSkillOnSlot(slotID, skill); skill = S_SUndefined; return false; } //returns random free skill slot (if any, otherwise -1) public function GetFreeSkillSlot() : int { var i, size : int; var skill : ESkill; size = ((W3PlayerAbilityManager)abilityManager).GetSkillSlotsCount(); for(i=1; i { if(!GetSkillOnSlot(i, skill)) continue; //if slot locked if(skill == S_SUndefined) //empty unlocked slot return i; } return -1; } ////////////////// // @attacks ////////////////// //performs an attack (mechanics wise) on given target and using given attack data protected function Attack( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array, attackAnimationName : name, hitTime : float, weaponEntity : CItemEntity) { var attackAction : W3Action_Attack; if(!PrepareAttackAction(hitTarget, animData, weaponId, parried, countered, parriedBy, attackAnimationName, hitTime, weaponEntity, attackAction)) return; //failed to create a valid attack action if ( attackAction.IsParried() && ( ((CNewNPC)attackAction.victim).IsShielded(attackAction.attacker) || ((CNewNPC)attackAction.victim).SignalGameplayEventReturnInt('IsDefending',0) == 1 ) ) { thePlayer.SetCanPlayHitAnim(true); thePlayer.ReactToReflectedAttack(attackAction.victim); } theTelemetry.LogWithLabel( TE_FIGHT_PLAYER_ATTACKS, attackAction.GetAttackName() ); //process action theGame.damageMgr.ProcessAction(attackAction); delete attackAction; } public function IsHeavyAttack(attackName : name) : bool { var skill : ESkill; var sup : bool; sup = super.IsHeavyAttack(attackName); if(sup) return true; if ( attackName == 'attack_heavy_special' ) return true; skill = SkillNameToEnum(attackName); return skill == S_Sword_2 || skill == S_Sword_s02; } public function IsLightAttack(attackName : name) : bool { var skill : ESkill; var sup : bool; sup = super.IsLightAttack(attackName); if(sup) return true; skill = SkillNameToEnum(attackName); return skill == S_Sword_1 || skill == S_Sword_s01; } public final function ProcessWeaponCollision() { var l_stateName : name; var l_weaponPosition : Vector; var l_weaponTipPos : Vector; var l_collidingPosition : Vector; var l_offset : Vector; var l_normal : Vector; var l_slotMatrix : Matrix; var l_distance : float; var l_materialName : name; var l_hitComponent : CComponent; var l_destructibleCmp : CDestructionSystemComponent; var barrel : COilBarrelEntity; //return; if( isCurrentlyDodging ) return; l_stateName = GetCurrentStateName(); if( !attackEventInProgress && l_stateName == 'CombatFists' ) return; CalcEntitySlotMatrix('r_weapon', l_slotMatrix); l_weaponPosition = MatrixGetTranslation( l_slotMatrix ); // Finding weapon's tip switch( l_stateName ) { case 'CombatFists': l_offset = MatrixGetAxisX( l_slotMatrix ); l_offset = VecNormalize( l_offset ) * 0.25f; break; // sword default: l_offset = MatrixGetAxisZ( l_slotMatrix ); l_offset = VecNormalize( l_offset ) * 1.f; break; } l_weaponTipPos = l_weaponPosition + l_offset; if( !attackEventInProgress ) { // If the weapon is not moving fast enough, do not play collision fx if( m_LastWeaponTipPos == Vector ( 0, 0, 0 ) ) l_distance = 0; else l_distance = VecDistance( l_weaponTipPos, m_LastWeaponTipPos ) ; //GetVisualDebug().AddText( 'LastWeaponTipText', "Last - dist: " + l_distance, m_LastWeaponTipPos, true, , Color( 249, 98, 158 ) ); //GetVisualDebug().AddArrow( 'OldDirectArrow', l_weaponPosition, m_LastWeaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) ); m_LastWeaponTipPos = l_weaponTipPos; if( l_distance < 0.35f ) return; } /*GetVisualDebug().AddSphere( 'WeaponPosition', 0.1f, l_weaponPosition, true, Color( 249, 98, 158 ) ); GetVisualDebug().AddText( 'WeaponTipText', "Weapon Tip", l_weaponTipPos, true, , Color( 249, 98, 158 ) ); GetVisualDebug().AddArrow( 'CollisionArrow', l_weaponPosition, l_weaponTipPos , 0.8f, 0.1f, 0.2f, true, Color( 249, 98, 158 ) );*/ m_LastWeaponTipPos = l_weaponTipPos; if ( !theGame.GetWorld().StaticTraceWithAdditionalInfo( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, l_materialName, l_hitComponent, m_WeaponFXCollisionGroupNames ) ) { // Test left fist if( l_stateName == 'CombatFists' ) { CalcEntitySlotMatrix('l_weapon', l_slotMatrix); l_weaponPosition = MatrixGetTranslation( l_slotMatrix ); l_offset = MatrixGetAxisX( l_slotMatrix ); l_offset = VecNormalize( l_offset ) * 0.25f; l_weaponTipPos = l_weaponPosition + l_offset; if( !theGame.GetWorld().StaticTrace( l_weaponPosition, l_weaponTipPos, l_collidingPosition, l_normal, m_WeaponFXCollisionGroupNames ) ) { return; } } else { return; } } if( !m_CollisionEffect ) { m_CollisionEffect = theGame.CreateEntity( m_CollisionFxTemplate, l_collidingPosition, EulerAngles(0,0,0) ); } m_CollisionEffect.Teleport( l_collidingPosition ); // Play hit effect switch( l_stateName ) { case 'CombatFists': m_CollisionEffect.PlayEffect('fist'); break; default: // Optimisation because IsSwordWooden() is heavy (around 0.13 ms) if( m_RefreshWeaponFXType ) { m_PlayWoodenFX = IsSwordWooden(); m_RefreshWeaponFXType = false; } if( m_PlayWoodenFX ) { m_CollisionEffect.PlayEffect('wood'); } else { switch( l_materialName ) { case 'wood_hollow': case 'wood_debris': case 'wood_solid': m_CollisionEffect.PlayEffect('wood'); break; case 'dirt_hard': case 'dirt_soil': case 'hay': m_CollisionEffect.PlayEffect('fist'); break; case 'stone_debris': case 'stone_solid': case 'clay_tile': case 'gravel_large': case 'gravel_small': case 'metal': case 'custom_sword': m_CollisionEffect.PlayEffect('sparks'); break; default: m_CollisionEffect.PlayEffect('wood'); break; } } break; } //don't ask... if(l_hitComponent) { barrel = (COilBarrelEntity)l_hitComponent.GetEntity(); if(barrel) { barrel.OnFireHit(NULL); //sets barrel on fire so that it explodes in a few sec return; } } // Destroy destructibles l_destructibleCmp = (CDestructionSystemComponent) l_hitComponent; if( l_destructibleCmp && l_stateName != 'CombatFists' ) { l_destructibleCmp.ApplyFracture(); } //GetVisualDebug().AddText( 'collisionText', "Collision Here", l_collidingPosition, true, , Color( 249, 98, 158 ) ); } public function ReactToReflectedAttack( target : CGameplayEntity) { var hp, dmg : float; var action : W3DamageAction; super.ReactToReflectedAttack(target); if ( !((CNewNPC)target).IsShielded(this) ) { action = new W3DamageAction in this; action.Initialize(target,this,NULL,'',EHRT_Reflect,CPS_AttackPower,true,false,false,false); action.AddEffectInfo(EET_Stagger); action.SetProcessBuffsIfNoDamage(true); theGame.damageMgr.ProcessAction( action ); delete action; } theGame.damageMgr.ProcessAction( action ); delete action; theGame.VibrateControllerLight();//player attack was reflected } ////////////////// // falling damage ////////////////// //return false when not falling function GetFallDist( out fallDist : float ) : bool { var fallDiff, jumpTotalDiff : float; // Get the falling height substateManager.m_SharedDataO.CalculateFallingHeights( fallDiff, jumpTotalDiff ); if ( fallDiff <= 0 ) return false; fallDist = fallDiff; return true; } function ApplyFallingDamage(heightDiff : float, optional reducing : bool) : float { var hpPerc : float; var tut : STutorialMessage; if ( IsSwimming() || FactsQuerySum("block_falling_damage") >= 1 ) return 0.0f; hpPerc = super.ApplyFallingDamage( heightDiff, reducing ); if(hpPerc > 0) { theGame.VibrateControllerHard();//player falling damage if(IsAlive()) { if(ShouldProcessTutorial('TutorialFallingDamage')) { FactsAdd("tutorial_falling_damage"); } if(FactsQuerySum("tutorial_falling_damage") > 1 && ShouldProcessTutorial('TutorialFallingRoll')) { //fill tutorial object data tut.type = ETMT_Hint; tut.tutorialScriptTag = 'TutorialFallingRoll'; tut.hintPositionType = ETHPT_DefaultGlobal; tut.hintDurationType = ETHDT_Long; tut.canBeShownInMenus = false; tut.glossaryLink = false; tut.markAsSeenOnShow = true; //show tutorial theGame.GetTutorialSystem().DisplayTutorial(tut); } } } return hpPerc; } //--------------------------------- STAMINA INDICATOR #B -------------------------------------- public function SetShowToLowStaminaIndication( value : float ) : void { fShowToLowStaminaIndication = value; } public function GetShowToLowStaminaIndication() : float { return fShowToLowStaminaIndication; } public final function IndicateTooLowAdrenaline() { SoundEvent("gui_no_adrenaline"); showTooLowAdrenaline = true; } ///////////////////////////////// protected function GotoCombatStateWithAction( initialAction : EInitialAction, optional initialBuff : CBaseGameplayEffect ) { if ( this.GetCurrentActionType() == ActorAction_Exploration ) ActionCancelAll(); ((W3PlayerWitcherStateCombatFists)this.GetState('CombatFists')).SetupState( initialAction, initialBuff ); this.GotoState( 'CombatFists' ); } /////////////////////////////////////////////////////////////////////////////////////////// // COMBAT public function IsThreat( actor : CActor, optional usePrecalcs : bool ) : bool { var npc : CNewNPC; var dist : float; var targetCapsuleHeight : float; var isDistanceExpanded : bool; var distanceToTarget : float; var attitude : EAIAttitude; if (!actor) { return false; } if ( finishableEnemiesList.Contains( actor ) ) { return true; } if ( !actor.IsAlive() || actor.IsKnockedUnconscious() ) { return false; } npc = (CNewNPC)actor; if (npc && npc.IsHorse() ) { return false; } if ( hostileEnemies.Contains( actor ) ) { return true; } //MS: We add a tolerance to make geralt go to alertfar everytime he runs away from npc if ( GetAttitudeBetween( this, actor ) == AIA_Hostile ) { if ( usePrecalcs ) { distanceToTarget = Distance2DBetweenCapsuleAndPoint( actor, this ) - targetingPrecalcs.playerRadius; } else { distanceToTarget = Distance2DBetweenCapsules( this, actor ); } // shortDistance = findMoveTargetDist + 5.0f; if ( distanceToTarget < findMoveTargetDist + 5.0f ) { return true; } if ( actor.IsInCombat() || this.IsHardLockEnabled() ) { targetCapsuleHeight = ( (CMovingPhysicalAgentComponent)actor.GetMovingAgentComponent() ).GetCapsuleHeight(); if ( targetCapsuleHeight >= 2.0f || npc.GetCurrentStance() == NS_Fly ) { // expandedDistance = 40.f; if ( distanceToTarget < 40.0f ) { return true; } } } } if ( actor.GetAttitudeGroup() == 'npc_charmed' ) { if ( theGame.GetGlobalAttitude( GetBaseAttitudeGroup(), actor.GetBaseAttitudeGroup() ) == AIA_Hostile ) { return true; } } return false; } function SetBIsCombatActionAllowed ( flag : bool ) { bIsCombatActionAllowed = flag; if ( !flag ) { SetBIsInCombatAction(true); } else { this.ProcessLAxisCaching(); //UnblockAction(EIAB_Interactions, 'InsideCombatAction' ); } //LogChannel('combatActionAllowed', "Is SET TO: " + flag ); } function GetBIsCombatActionAllowed() : bool { return bIsCombatActionAllowed; } function SetCombatAction( action : EBufferActionType ) { currentCombatAction = action; } function GetCombatAction() : EBufferActionType { return currentCombatAction; } protected function WhenCombatActionIsFinished() { if(IsThrowingItem() || IsThrowingItemWithAim() ) { if(inv.IsItemBomb(selectedItemId)) { BombThrowAbort(); } else { ThrowingAbort(); } } if ( this.GetCurrentStateName() != 'DismountHorse' ) OnRangedForceHolster( true ); //SetBehaviorVariable( 'combatActionType', (int)CAT_None2); } public function IsInCombatAction_Attack(): bool { if ( IsInCombatAction_NonSpecialAttack() || IsInCombatAction_SpecialAttack() ) return true; else return false; } public function IsInCombatAction_NonSpecialAttack(): bool { if ( IsInCombatAction() && ( GetCombatAction() == EBAT_LightAttack || GetCombatAction() == EBAT_HeavyAttack ) ) return true; else return false; } public function IsInSpecificCombatAction ( specificCombatAction : EBufferActionType ) : bool { if ( IsInCombatAction() && GetCombatAction() == specificCombatAction ) return true; else return false; } public function IsInRunAnimation() : bool { return isInRunAnimation; } //I need to call it after scene ends thats why it's public. PF public function SetCombatIdleStance( stance : float ) { SetBehaviorVariable( 'combatIdleStance', stance ); SetBehaviorVariable( 'CombatStanceForOverlay', stance ); if ( stance == 0.f ) LogChannel( 'ComboInput', "combatIdleStance = Left" ); else LogChannel( 'ComboInput', "combatIdleStance = Right" ); } public function GetCombatIdleStance() : float { // 0.f == Left return GetBehaviorVariable( 'combatIdleStance' ); } protected var isRotatingInPlace : bool; event OnRotateInPlaceStart() { isRotatingInPlace = true; } event OnRotateInPlaceEnd() { isRotatingInPlace = false; } event OnFullyBlendedIdle() { if ( bLAxisReleased ) { ResetRawPlayerHeading(); ResetCachedRawPlayerHeading(); defaultLocomotionController.ResetMoveDirection(); } } event OnRunLoopStart() { EnableRunCamera( true ); } event OnRunLoopEnd() { EnableRunCamera( false ); } event OnCombatActionStartBehgraph() { var buff : CBaseGameplayEffect; var action : EBufferActionType; var cost, delay : float; // Block saves //theGame.CreateNoSaveLock( noSaveLockCombatActionName, noSaveLockCombatAction, true ); OnCombatActionStart(); //Pause the stamina regen for as long as we're doing combat actions. //Pause only once to avoid the pause counter from increasing with each lock buff = GetBuff(EET_AutoStaminaRegen); action = PerformingCombatAction(); switch ( action ) { case EBAT_LightAttack : { abilityManager.GetStaminaActionCost(ESAT_LightAttack, cost, delay); } break; case EBAT_HeavyAttack : { abilityManager.GetStaminaActionCost(ESAT_HeavyAttack, cost, delay); } break; case EBAT_ItemUse : { abilityManager.GetStaminaActionCost(ESAT_UsableItem, cost, delay); } break; case EBAT_Parry : { abilityManager.GetStaminaActionCost(ESAT_Parry, cost, delay); } break; case EBAT_Dodge : { abilityManager.GetStaminaActionCost(ESAT_Dodge, cost, delay); } break; case EBAT_Roll : abilityManager.GetStaminaActionCost(ESAT_Roll, cost, delay); break; case EBAT_SpecialAttack_Light : { abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s01)); } break; case EBAT_SpecialAttack_Heavy : { abilityManager.GetStaminaActionCost(ESAT_Ability, cost, delay, 0,0, GetSkillAbilityName(S_Sword_s02)); } break; case EBAT_Roll : { abilityManager.GetStaminaActionCost(ESAT_Evade, cost, delay); } break; /* case EBAT_Ciri_SpecialAttack : { cost = GetStaminaActionCost(); } break; */ default : ; } if( (!buff || !buff.IsPaused('InsideCombatAction')) && delay > 0 ) PauseEffects(EET_AutoStaminaRegen, 'InsideCombatAction'); } public function HolsterUsableItem() : bool { return holsterUsableItem; } private var isInGuardedState : bool; public function IsInGuardedState() : bool { return isInGuardedState; } event OnGuardedStart() { isInParryOrCounter = true; isInGuardedState = true; } event OnGuardedEnd() { isInParryOrCounter = false; isInGuardedState = false; } private var restoreUsableItem : bool; private var holsterUsableItem : bool; event OnCombatActionStart() { //Block Actions //BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart' ); BlockAction( EIAB_UsableItem, 'OnCombatActionStart' ); BlockAction( EIAB_CallHorse, 'OnCombatActionStart' ); /*if ( !IsGuarded() ) SetParryTarget( NULL );*/ LogChannel('combatActionAllowed',"FALSE OnCombatActionStart"); SetBIsCombatActionAllowed( false ); SetBIsInputAllowed( false, 'OnCombatActionStart' ); //lastAxisInputIsMovement = true; ClearFinishableEnemyList( 0.f, 0 ); bIsInHitAnim = false; //Holster Crossbow if it's held //if ( inv.IsItemCrossbow( inv.GetItemFromSlot( 'l_weapon' ) ) )//&& GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Crossbow ) if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) { CleanCombatActionBuffer(); SetIsAimingCrossbow( false ); OnRangedForceHolster( false, true ); } //Holster UsableItem if it's held holsterUsableItem = false; if ( thePlayer.IsHoldingItemInLHand() ) // && !thePlayer.IsUsableItemLBlocked() ) { if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_CastSign ) holsterUsableItem = true; else if ( GetBehaviorVariable( 'combatActionType' ) == (int)CAT_Attack ) { if ( this.GetCurrentStateName() == 'CombatFists' ) holsterUsableItem = true; } } if ( holsterUsableItem ) { thePlayer.SetPlayerActionToRestore ( PATR_None ); thePlayer.OnUseSelectedItem( true ); restoreUsableItem = true; } //Stop Geralt from automatically attacking while in AttackApproach when Player performs a non-attack combat action if ( GetBehaviorVariable( 'combatActionType' ) != (int)CAT_Attack && GetBehaviorVariable( 'combatActionType' ) != (int)CAT_PreAttack ) { RemoveTimer( 'ProcessAttackTimer' ); RemoveTimer( 'AttackTimerEnd' ); UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' ); } else { //MS: Do not remove this!! The attack to idle transition states will not work correctly if you change weapon mid-attack. BlockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' ); } //GetMovingAgentComponent().SnapToNavigableSpace(true); } var isInParryOrCounter : bool; event OnParryOrCounterStart() { isInParryOrCounter = true; OnCombatActionStartBehgraph(); } event OnParryOrCounterEnd() { isInParryOrCounter = false; OnCombatActionEnd(); SetBIsInCombatAction( false ); } //called when a combat action is completed (e.g. single hit in a combo sequence) event OnCombatActionEnd() { var item : SItemUniqueId; var combatActionType : float; super.OnCombatActionEnd(); //Unblock Actions BlockAllActions( 'OnCombatActionStart', false ); UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' ); //why? this way after EACH attack you reset it - what's the point then? //ResetUninterruptedHitsCount(); oTCameraOffset = 0.f; oTCameraPitchOffset = 0.f; //LogChannel('combatActionAllowed',"TRUE OnCombatActionEnd"); SetBIsCombatActionAllowed( true ); //reapply critical buff if any //Z ReapplyCriticalBuff(); SetBIsInputAllowed( true, 'OnCombatActionEnd' ); SetCanPlayHitAnim( true ); EnableFindTarget( true ); SetIsCurrentlyDodging( false ); SetFinisherVictim( NULL ); OnBlockAllCombatTickets( false ); LogStamina("CombatActionEnd"); //GetMovingAgentComponent().SnapToNavigableSpace(false); SetAttackActionName(''); combatActionType = GetBehaviorVariable('combatActionType'); //clean-up after special attack heavy finishes if(GetBehaviorVariable('combatActionType') == (int)CAT_SpecialAttack) { theGame.GetGameCamera().StopAnimation( 'camera_shake_loop_lvl1_1' ); OnSpecialAttackHeavyActionProcess(); } // Do we need to interrupt? substateManager.ReactToChanceToFallAndSlide(); } event OnCombatActionFriendlyStart() { SetBIsInCombatActionFriendly(true); OnCombatActionStart(); } event OnCombatActionFriendlyEnd() { SetBIsInCombatActionFriendly(false); OnCombatActionEnd(); SetBIsInCombatAction(false); //RaiseForceEvent( 'ForceIdle' ); } event OnHitStart() { var timeLeft : float; var currentEffects : array; var none : SAbilityAttributeValue; CancelHoldAttacks(); WhenCombatActionIsFinished(); if ( isInFinisher ) { if ( finisherTarget ) ( (CNewNPC)finisherTarget ).SignalGameplayEvent( 'FinisherInterrupt' ); isInFinisher = false; finisherTarget = NULL; SetBIsCombatActionAllowed( true ); } bIsInHitAnim = true; OnCombatActionStart(); //"because it's needed" //OnCombatActionStart pauses the regen and we don't want that ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction'); if( GetHealthPercents() < 0.3f ) { PlayBattleCry('BattleCryBadSituation', 0.10f, true ); } else { PlayBattleCry('BattleCryBadSituation', 0.05f, true ); } } event OnHitStartSwimming() { OnRangedForceHolster( true, true, false ); } // modXTfinishers BEGIN public var actionContext : XTFinishersActionContext; public function LoadActionContext(context : XTFinishersActionContext) { actionContext = context; } // modXTFinishers END private var finisherSaveLock : int; event OnFinisherStart() { var currentEffects : array; theGame.CreateNoSaveLock("Finisher",finisherSaveLock,true,false); isInFinisher = true; finisherTarget = slideTarget; OnCombatActionStart(); CancelHoldAttacks(); // modXTFinishers BEGIN theGame.xtFinishersMgr.eventMgr.FireEvent(theGame.xtFinishersMgr.consts.FINISHER_EVENT_ID, CreateXTFinishersActionContextData(theGame.xtFinishersMgr.eventMgr, actionContext)); // modXTFinishers END PlayFinisherCameraAnimation( theGame.GetSyncAnimManager().GetFinisherCameraAnimName() ); this.AddAnimEventCallback('SyncEvent','OnFinisherAnimEvent_SyncEvent'); SetImmortalityMode( AIM_Invulnerable, AIC_SyncedAnim ); } public function IsPerformingFinisher() : bool { return isInFinisher; } private function PlayFinisherCameraAnimation( cameraAnimName : name ) { var camera : CCustomCamera = theGame.GetGameCamera(); var animation : SCameraAnimationDefinition; if (IsLastEnemyKilled() && theGame.GetWorld().NavigationCircleTest( this.GetWorldPosition(), 3.f ) ) if (actionContext.finisherCam.active) { theGame.xtFinishersMgr.eventMgr.FireEvent(theGame.xtFinishersMgr.consts.FINISHER_CAM_PRE_EVENT_ID, CreateXTFinishersActionContextData(theGame.xtFinishersMgr.eventMgr, actionContext)); if (actionContext.finisherCam.active) { camera.StopAnimation('camera_shake_hit_lvl3_1' ); animation.animation = cameraAnimName; animation.priority = CAP_Highest; animation.blendIn = 0.15f; animation.blendOut = 1.0f; animation.weight = 1.f; animation.speed = 1.0f; animation.reset = true; camera.PlayAnimation( animation ); //thePlayer.AddTimer( 'RemoveFinisherCameraAnimationCheck', 0.01, true ); thePlayer.EnableManualCameraControl( false, 'Finisher' ); theGame.xtFinishersMgr.eventMgr.FireEvent(theGame.xtFinishersMgr.consts.FINISHER_CAM_EVENT_ID, CreateXTFinishersActionContextData(theGame.xtFinishersMgr.eventMgr, actionContext)); } } // modXTFinishers END } public function IsLastEnemyKilled() : bool { var tempMoveTargets : array; FindMoveTarget(); tempMoveTargets = GetMoveTargets(); if ( tempMoveTargets.Size() <= 0 || !thePlayer.IsThreat( tempMoveTargets[0] ) ) return true; return false; } event OnFinisherAnimEvent_SyncEvent( animEventName : name, animEventType : EAnimationEventType, animInfo : SAnimationEventAnimInfo ) { if ( finisherTarget ) ( (CNewNPC)finisherTarget ).SignalGameplayEvent('FinisherKill'); finisherTarget = NULL; } event OnFinisherEnd() { isInFinisher = false; finisherTarget = NULL; theGame.ReleaseNoSaveLock(finisherSaveLock); this.RemoveAnimEventCallback('SyncEvent'); //SetIsPerformingPhaseChangeAnimation( false ); // for eredin fight // modXTFinishers BEGIN if (actionContext) { delete actionContext; actionContext = NULL; } // modXTFinishers END SetImmortalityMode( AIM_None, AIC_SyncedAnim ); theGame.RemoveTimeScale( 'AnimEventSlomoMo' ); AddTimer( 'FinisherEndEnableCamera', 0.5f ); //OnBlockAllCombatTickets( false ); OnCombatActionEnd(); OnCombatActionEndComplete(); } private timer function FinisherEndEnableCamera( dt : float, id : int ) { thePlayer.EnableManualCameraControl( true, 'Finisher' ); } public function SpawnFinisherBlood() { var weaponEntity : CEntity; var weaponSlotMatrix : Matrix; var bloodFxPos : Vector; var bloodFxRot : EulerAngles; var tempEntity : CEntity; weaponEntity = this.GetInventory().GetItemEntityUnsafe( GetInventory().GetItemFromSlot('r_weapon') ); weaponEntity.CalcEntitySlotMatrix( 'blood_fx_point', weaponSlotMatrix ); bloodFxPos = MatrixGetTranslation( weaponSlotMatrix ); bloodFxRot = this.GetWorldRotation();//MatrixGetRotation( weaponSlotMatrix ); tempEntity = theGame.CreateEntity( (CEntityTemplate)LoadResource('finisher_blood'), bloodFxPos, bloodFxRot); tempEntity.PlayEffect('crawl_blood'); } //called when all combat actions have ended (e.g. whole combo) event OnCombatActionEndComplete() { var buff : CBaseGameplayEffect; buff = ChooseCurrentCriticalBuffForAnim(); SetCombatAction( EBAT_EMPTY ); //Unblock Actions what you wann UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart' ); UnblockAction( EIAB_OpenInventory, 'OnCombatActionStart' ); UnblockAction( EIAB_UsableItem, 'OnCombatActionStart' ); UnblockAction( EIAB_DrawWeapon, 'OnCombatActionStart_Attack' ); SetUnpushableTarget( NULL ); SetBIsInCombatAction(false); SetIsCurrentlyDodging(false); SetMoveTargetChangeAllowed( true ); SetCanPlayHitAnim( true ); SetFinisherVictim( NULL ); this.RemoveBuffImmunity(EET_Burning, 'AnimEvent_RemoveBurning'); if ( rangedWeapon && rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' && !buff ) { ClearCustomOrientationInfoStack(); SetSlideTarget( NULL ); } UnblockAction( EIAB_Crossbow, 'OnForceHolster' ); specialAttackCamera = false; bIsRollAllowed = false; if ( bLAxisReleased ) { ResetRawPlayerHeading(); ResetCachedRawPlayerHeading(); } //reapply critical buff if any ReapplyCriticalBuff(); SetBIsInputAllowed( true, 'OnCombatActionEndComplete' ); //stamina regen is paused as long as we are doing some combat actions ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction'); bIsInHitAnim = false; SetBIsCombatActionAllowed( true ); m_LastWeaponTipPos = Vector(0, 0, 0, 0 ); //free tickets this.AddTimer('FreeTickets',3.f,false); // remove save lock //theGame.ReleaseNoSaveLockByName( noSaveLockCombatActionName ); } event OnMovementFullyBlended() { SetBehaviorVariable( 'isPerformingSpecialAttack', 0.f ); if ( restoreUsableItem ) { restoreUsableItem = false; SetPlayerActionToRestore ( PATR_Default ); OnUseSelectedItem(); } } event OnCombatMovementStart() { SetCombatIdleStance( 1.f ); OnCombatActionEndComplete(); } timer function FreeTickets( dt : float, id : int ) { FreeTicketAtCombatTarget(); } /* These declarations are needed here only to call event with the same name inside combat state (there's no other way to call it!). */ event OnGuardedReleased(){} event OnPerformAttack( playerAttackType : name ){} event OnPerformEvade( playerEvadeType : EPlayerEvadeType ){} event OnInterruptAttack(){} event OnPerformGuard(){} event OnSpawnHorse(){} event OnDismountActionScriptCallback(){} event OnHorseSummonStart() { thePlayer.BlockAction(EIAB_CallHorse, 'HorseSummon'); thePlayer.BlockAction(EIAB_Signs, 'HorseSummon'); thePlayer.BlockAction(EIAB_Crossbow, 'HorseSummon'); thePlayer.BlockAction(EIAB_UsableItem, 'HorseSummon'); thePlayer.BlockAction(EIAB_ThrowBomb, 'HorseSummon'); thePlayer.BlockAction(EIAB_SwordAttack, 'HorseSummon'); thePlayer.BlockAction(EIAB_Jump, 'HorseSummon'); thePlayer.BlockAction(EIAB_Dodge, 'HorseSummon'); thePlayer.BlockAction(EIAB_LightAttacks, 'HorseSummon'); thePlayer.BlockAction(EIAB_HeavyAttacks, 'HorseSummon'); thePlayer.BlockAction(EIAB_SpecialAttackLight, 'HorseSummon'); thePlayer.BlockAction(EIAB_SpecialAttackHeavy, 'HorseSummon'); horseSummonTimeStamp = theGame.GetEngineTimeAsSeconds(); } event OnHorseSummonStop() { thePlayer.BlockAllActions('HorseSummon',false); } /* CombatAction events when on vehicles */ event OnCombatActionStartVehicle( action : EVehicleCombatAction ) { this.SetBIsCombatActionAllowed( false ); if ( action != EHCA_ShootCrossbow ) { SetIsAimingCrossbow( false ); OnRangedForceHolster(); } } event OnCombatActionEndVehicle() { this.SetBIsCombatActionAllowed( true ); } //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @CRITICAL STATES ///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// protected function CriticalBuffInformBehavior(buff : CBaseGameplayEffect) { /*if ( this.GetCurrentStateName() == 'Exploration' || this.GetCurrentStateName() == 'AimThrow' ) GotoCombatStateWithAction( IA_CriticalState, buff ); else {*/ if( !CanAnimationReactToCriticalState( buff ) ) { return; } // if ( IsInCombatAction() ) // RaiseEvent('ForceBlendOut'); SetBehaviorVariable( 'CriticalStateType', (int)GetBuffCriticalType(buff) ); SetBehaviorVariable( 'bCriticalState', 1); if(CriticalBuffUsesFullBodyAnim(buff)) RaiseEvent('CriticalState'); SetBehaviorVariable( 'IsInAir', (int)IsInAir()); LogCritical("Sending player critical state event for <<" + buff.GetEffectType() + ">>"); //} } private function CanAnimationReactToCriticalState( buff : CBaseGameplayEffect ) : bool { var buffCritical : W3CriticalEffect; var buffCriticalDOT : W3CriticalDOTEffect; var isHeavyCritical : bool; isHeavyCritical = false; // Find out if it is a heavy critical state buffCritical = ( W3CriticalEffect ) buff; if( buffCritical ) { isHeavyCritical = buffCritical.explorationStateHandling == ECH_HandleNow; } else { buffCriticalDOT = ( W3CriticalDOTEffect ) buff; if( buffCriticalDOT ) { isHeavyCritical = buffCriticalDOT.explorationStateHandling == ECH_HandleNow; } } // If it is not, we may skip it if( !isHeavyCritical ) { if( !CanReactToCriticalState() ) { return false; } } return true; } public function CanReactToCriticalState() : bool { return substateManager.CanReactToHardCriticalState(); } event OnCriticalStateAnimStart() { var heading : float; var newCritical : ECriticalStateType; var newReqCS : CBaseGameplayEffect; OnCombatActionEndComplete(); //abort throwing if super was processed properly newReqCS = newRequestedCS; if(super.OnCriticalStateAnimStart()) { //WhenCombatActionIsFinished(); RemoveTimer( 'IsItemUseInputHeld' ); keepRequestingCriticalAnimStart = false; CancelHoldAttacks(); //knockdown direction // No knockdown when using a vehicule: the vehicule will handle the knock down logic //PFTODO //we need this for NPCs also (knockdown dir) if(!IsUsingVehicle()) { newCritical = GetBuffCriticalType(newReqCS); if(newCritical == ECST_HeavyKnockdown || newCritical == ECST_Knockdown || newCritical == ECST_Stagger || newCritical == ECST_Ragdoll || newCritical == ECST_LongStagger ) { if(newReqCS.GetCreator()) heading = VecHeading(newReqCS.GetCreator().GetWorldPosition() - GetWorldPosition()); else heading = GetHeading(); //this.GetMovingAgentComponent().GetMovementAdjustor().CancelAll(); SetCustomRotation( 'Knockdown', heading, 2160.f, 0.1f, true ); if ( newCritical != ECST_Stagger && newCritical != ECST_LongStagger ) substateManager.ReactOnCriticalState( true ); } } return true; } //SetBehaviorVariable( 'bCriticalStopped', 1); return false; } /* Called when new critical effect has started This will interrupt current critical state returns true if the effect got fired properly */ public function StartCSAnim(buff : CBaseGameplayEffect) : bool { SetBehaviorVariable( 'bCriticalStopped', 0 ); if(super.StartCSAnim(buff)) { if(!CriticalBuffUsesFullBodyAnim(buff)) { OnCriticalStateAnimStart(); } ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction'); keepRequestingCriticalAnimStart = true; AddTimer('RequestCriticalAnimStart', 0, true); //RequestCriticalAnimStart(0); return true; } return false; } public function CriticalEffectAnimationInterrupted(reason : string) : bool { var ret : bool; //for debug LogCriticalPlayer("R4Player.CriticalEffectAnimationInterrupted() - because: " + reason); ret = super.CriticalEffectAnimationInterrupted(reason); if(ret) { keepRequestingCriticalAnimStart = false; } substateManager.ReactOnCriticalState( false ); return ret; } public function CriticalStateAnimStopped(forceRemoveBuff : bool) { LogCriticalPlayer("R4Player.CriticalStateAnimStopped() - forced: " + forceRemoveBuff); super.CriticalStateAnimStopped(forceRemoveBuff); substateManager.ReactOnCriticalState( false ); } // keeps requesting (sending event) to enter critical states anim state in behavior timer function RequestCriticalAnimStart(dt : float, id : int) { if(keepRequestingCriticalAnimStart) { if(newRequestedCS && newRequestedCS.GetDurationLeft() > 0) { CriticalBuffInformBehavior(newRequestedCS); } else { keepRequestingCriticalAnimStart = false; RemoveTimer('RequestCriticalAnimStart'); } } else { RemoveTimer('RequestCriticalAnimStart'); } } event OnRagdollUpdate(progress : float) { //super.OnRagdollUpdate(progress); SetIsInAir(progress == 0); } // getting from ragdoll after certain time has passed event OnRagdollOnGround() { // try to getup immediately as currently when laying on ground we might be constantly switched between on ground and in air TryToEndRagdollOnGround( 0.0f ); } event OnRagdollInAir() { RemoveTimer('TryToEndRagdollOnGround'); } event OnNoLongerInRagdoll() { RemoveTimer('TryToEndRagdollOnGround'); } timer function TryToEndRagdollOnGround( td : float, optional id : int) { var critical : CBaseGameplayEffect; var type : EEffectType; critical = GetCurrentlyAnimatedCS(); if(critical) { type = critical.GetEffectType(); if(type == EET_Knockdown || type == EET_HeavyKnockdown || type == EET_Ragdoll) { // 2.5 seconds is not that long but this is not ragdoll simulator :) if (critical.GetTimeActive() >= 2.5f) { SetIsInAir(false); RequestCriticalAnimStop(); RemoveTimer('TryToEndRagdollOnGround'); } else { AddTimer('TryToEndRagdollOnGround', 0.2f, true); } return; } } // not in critical or type differs RemoveTimer('TryToEndRagdollOnGround'); } public function RequestCriticalAnimStop(optional dontSetCriticalToStopped : bool) { var buff : CBaseGameplayEffect; buff = GetCurrentlyAnimatedCS(); if(buff && !CriticalBuffUsesFullBodyAnim(buff)) { CriticalStateAnimStopped(false); } if(!buff || !CriticalBuffUsesFullBodyAnim(buff)) { SetBehaviorVariable( 'bCriticalState', 0); } super.RequestCriticalAnimStop(dontSetCriticalToStopped); } //////////////////////////////////////////////////////////////////////////////////////////// // @Buffs @Effects //////////////////////////////////////////////////////////////////////////////////////////// public function SimulateBuffTimePassing(simulatedTime : float) { effectManager.SimulateBuffTimePassing(simulatedTime); } public function AddEffectDefault(effectType : EEffectType, creat : CGameplayEntity, srcName : string, optional isSignEffect : bool) : EEffectInteract { var params : SCustomEffectParams; /* Welcome to the Ancient Pit. If you're here reading this then you're doomed... You're probably asking why someone is overriding default effect durations with some custom arbitrary numbers... The thuth is: noone remembers... But we need this and you cannot remove it or shit will start falling apart. */ if(effectType == EET_Stagger || effectType == EET_LongStagger || effectType == EET_Knockdown || effectType == EET_HeavyKnockdown) { params.effectType = effectType; params.creator = creat; params.sourceName = srcName; params.isSignEffect = isSignEffect; if ( effectType == EET_Stagger ) params.duration = 1.83; else if ( effectType == EET_LongStagger ) params.duration = 4; else if ( effectType == EET_Knockdown ) params.duration = 2.5; else if ( effectType == EET_HeavyKnockdown ) params.duration = 4; return super.AddEffectCustom(params); } else { return super.AddEffectDefault(effectType, creat, srcName, isSignEffect); } } //////////////////////////////////////////////////////////////////////////////////////////// //a cheat to ressurect player public function CheatResurrect() { if(IsAlive()) return; SetAlive(true); SetKinematic(true); delete abilityManager; delete effectManager; SetAbilityManager(); //defined in inheriting classes but must be called before setting any other managers - sets skills and stats abilityManager.Init(this, GetCharacterStats(), false, theGame.GetDifficultyMode()); SetEffectManager(); abilityManager.PostInit(); //called after other managers are ready EnableFindTarget( true ); SetBehaviorVariable( 'Ragdoll_Weight', 0.f ); RaiseForceEvent( 'RecoverFromRagdoll' ); SetCanPlayHitAnim( true ); SetBehaviorVariable( 'CriticalStateType', (int)ECST_None ); //if( GetCurrentStateName() != 'CombatSteel') // PushState( 'CombatSteel' ); //else GoToStateIfNew('Exploration'); ( (CDismembermentComponent)this.GetComponent( 'Dismemberment' ) ).ClearVisibleWound(); SetIsInAir(false); //might block getup from ragdol in knockdown theInput.SetContext('Exploration'); ResetDeathType(); ForceUnlockAllInputActions(false); theGame.CloseMenu('DeathScreenMenu'); //restore sounds theSound.LeaveGameState(ESGS_Death); theGame.ReleaseNoSaveLock(deathNoSaveLock); } //////////////////////////////////////////////////////////////////////////////////////////// public function SetIsInsideInteraction(b : bool) {isInsideInteraction = b;} public function IsInsideInteraction() : bool {return isInsideInteraction;} public function SetIsInsideHorseInteraction( b : bool, horse : CEntity ) { isInsideHorseInteraction = b; horseInteractionSource = horse; } public function IsInsideHorseInteraction() : bool {return isInsideHorseInteraction;} event OnInteractionActivationTest( interactionComponentName : string, activator : CEntity ) { if ( interactionComponentName == "ClimbLadder" ) { if( PlayerHasLadderExplorationReady() ) { return true; } } return false; } private function PlayerHasLadderExplorationReady() : bool { if( !substateManager.CanInteract() ) { return false; } if( !substateManager.m_SharedDataO.HasValidLadderExploration() ) { return false; } return true; } //////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// @COMBAT ///////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// public function SetGuarded(flag : bool) { super.SetGuarded(flag); if(flag && FactsQuerySum("tut_fight_use_slomo") > 0) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_TutorialFight) ); FactsRemove("tut_fight_slomo_ON"); } } public function IsGuarded() : bool { return super.IsGuarded() && ( !rangedWeapon || rangedWeapon.GetCurrentStateName() == 'State_WeaponWait' ); } //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////// @THROWABLE @BOMBS @PETARDS @Usable /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// public function GetSelectedItemId() : SItemUniqueId {return selectedItemId;} public function ClearSelectedItemId() {selectedItemId = GetInvalidUniqueId();} public function IsHoldingItemInLHand() : bool { return currentlyEquipedItemL != GetInvalidUniqueId(); } public function GetCurrentlyUsedItemL () : W3UsableItem { return currentlyUsedItemL; } public function SetPlayerActionToRestore ( actionToRestoreType : EPlayerActionToRestore ) { playerActionToRestore = actionToRestoreType; } public function IsCurrentlyUsingItemL () : bool { return currentlyUsingItem; } function BlockSlotsOnLItemUse () { var slotsToBlock : array; slotsToBlock.PushBack( 'Slot1' ); slotsToBlock.PushBack( 'Slot2' ); slotsToBlock.PushBack( 'Slot3' ); slotsToBlock.PushBack( 'Slot4' ); slotsToBlock.PushBack( 'Slot5' ); slotsToBlock.PushBack( 'Yrden' ); slotsToBlock.PushBack( 'Quen' ); slotsToBlock.PushBack( 'Igni' ); slotsToBlock.PushBack( 'Axii' ); slotsToBlock.PushBack( 'Aard' ); EnableRadialSlotsWithSource ( false, slotsToBlock, 'usableItemL' ); } function UnblockSlotsOnLItemUse () { var slotsToBlock : array; slotsToBlock.PushBack( 'Slot1' ); slotsToBlock.PushBack( 'Slot2' ); slotsToBlock.PushBack( 'Slot3' ); slotsToBlock.PushBack( 'Slot4' ); slotsToBlock.PushBack( 'Slot5' ); slotsToBlock.PushBack( 'Yrden' ); slotsToBlock.PushBack( 'Quen' ); slotsToBlock.PushBack( 'Igni' ); slotsToBlock.PushBack( 'Axii' ); slotsToBlock.PushBack( 'Aard' ); EnableRadialSlotsWithSource ( true, slotsToBlock, 'usableItemL' ); } function IsUsableItemLBlocked () : bool { return isUsableItemBlocked; } function HideUsableItem( optional force : bool ) { if( currentlyEquipedItemL != GetInvalidUniqueId() ) { if ( force ) { if (!RaiseEvent( 'ItemEndL' ) ) { OnUsingItemsReset(); } return; } RaiseEvent( 'ItemUseL' ); } } function ProcessUsableItemsTransition ( actionToRestore : EPlayerActionToRestore ) { var category : name; var signSkill : ESkill; category = inv.GetItemCategory ( selectedItemId ); signSkill = SignEnumToSkillEnum( GetEquippedSign()); switch ( actionToRestore ) { case PATR_None: if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); return; case PATR_Default: if ( IsSlotQuickslot( inv.GetSlotForItemId ( selectedItemId )) && category == 'usable' && currentlyEquipedItemL != selectedItemId ) { if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); OnUseSelectedItem(); return; } break; case PATR_Crossbow: if ( inv.IsItemCrossbow ( selectedItemId ) ) { if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); SetIsAimingCrossbow( true ); if ( theInput.IsActionPressed( 'ThrowItem' ) ) SetupCombatAction( EBAT_ItemUse, BS_Pressed ); else { SetupCombatAction( EBAT_ItemUse, BS_Pressed ); SetupCombatAction( EBAT_ItemUse, BS_Released ); } return; } break; case PATR_CastSign: if( signSkill != S_SUndefined && playerActionToRestore == PATR_CastSign ) { if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); if( HasStaminaToUseSkill( signSkill, false ) ) { if( GetInvalidUniqueId() != inv.GetItemFromSlot( 'l_weapon' ) ) PushCombatActionOnBuffer( EBAT_CastSign, BS_Pressed ); else SetupCombatAction( EBAT_CastSign, BS_Pressed ); } else { thePlayer.SoundEvent("gui_no_stamina"); } return; } break; case PATR_ThrowBomb: if ( inv.IsItemBomb ( selectedItemId ) ) { if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); PrepareToAttack(); SetupCombatAction( EBAT_ItemUse, BS_Pressed ); return; } break; case PATR_CallHorse: theGame.OnSpawnPlayerHorse(); break; default: if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); return; } if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); } function GetUsableItemLtransitionAllowed () : bool { return isUsableItemLtransitionAllowed; } function SetUsableItemLtransitionAllowed ( isAllowed : bool) { isUsableItemLtransitionAllowed = isAllowed; } event OnItemUseLUnBlocked () { if ( isUsableItemBlocked ) { isUsableItemBlocked = false; UnblockSlotsOnLItemUse (); } } event OnItemUseLBlocked () { if ( !isUsableItemBlocked ) { isUsableItemBlocked = true; BlockSlotsOnLItemUse (); } } event OnUsingItemsReset() { if ( currentlyUsingItem ) { OnItemUseLUnBlocked (); OnUsingItemsComplete(); } } event OnUsingItemsComplete () { if ( isUsableItemBlocked ) { OnItemUseLUnBlocked (); } currentlyUsingItem = false; if ( GetUsableItemLtransitionAllowed () ) { ProcessUsableItemsTransition( playerActionToRestore ); } else { if ( currentlyUsedItemL ) { inv.UnmountItem( currentlyEquipedItemL, true ); } currentlyEquipedItemL = GetInvalidUniqueId(); } SetPlayerActionToRestore ( PATR_Default ); } event OnUseSelectedItem( optional force : bool ) { var category : name; var itemEntity : W3UsableItem; if ( isUsableItemBlocked && !force ) { return false; } if ( IsCastingSign() ) return false; if ( currentlyEquipedItemL != GetInvalidUniqueId() ) { SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( currentlyEquipedItemL ) ); if ( force ) { if ( RaiseEvent( 'ItemEndL' ) ) { SetUsableItemLtransitionAllowed ( true ); return true; } } else { if ( RaiseEvent( 'ItemUseL' ) ) { SetUsableItemLtransitionAllowed ( true ); return true; } } } else { category = inv.GetItemCategory( selectedItemId ); if( category != 'usable' ) { return false; } SetBehaviorVariable( 'SelectedItemL', (int)GetUsableItemTypeById( selectedItemId ) ); if( RaiseEvent( 'ItemUseL' ) ) { currentlyEquipedItemL = selectedItemId; SetUsableItemLtransitionAllowed ( false ); currentlyUsingItem = true; return true; } inv.UnmountItem( selectedItemId, true ); } } protected saved var currentlyUsingItem : bool; public function ProcessUseSelectedItem( itemEntity : W3UsableItem, optional shouldCallOnUsed : bool ) { currentlyUsedItemL = itemEntity; DrainStamina(ESAT_UsableItem); if ( shouldCallOnUsed ) { currentlyUsedItemL.OnUsed( thePlayer ); } } function GetUsableItemTypeById ( itemId : SItemUniqueId ) : EUsableItemType { var itemName : name; itemName = inv.GetItemName ( itemId ); return theGame.GetDefinitionsManager().GetUsableItemType ( itemName ); } // Starts the 'WaitForItemSpawnAndProccesTask' task public function StartWaitForItemSpawnAndProccesTask() { AddTimer( 'WaitForItemSpawnAndProccesTask', 0.001f, true,,,,true ); } // Kills the 'WaitForItemSpawnAndProccesTask' task public function KillWaitForItemSpawnAndProccesTask() { RemoveTimer ( 'WaitForItemSpawnAndProccesTask' ); } // Informs the 'WaitForItemSpawnAndProccesTask' task, that selected item should be used ASAP. // Flag will be reset by the task itself public function AllowUseSelectedItem() { m_useSelectedItemIfSpawned = true; } // Task waits for inventory to created selected item. Item will be used ASAP as the task is allowed to do so. // Right after that - it kills itself. timer function WaitForItemSpawnAndProccesTask( timeDelta : float , id : int ) { var itemEntity : W3UsableItem; var canTaskBeKilled : bool; canTaskBeKilled = false; if ( IsCastingSign() ) { return; } // selectad item is wrong! if ( selectedItemId == GetInvalidUniqueId() ) { canTaskBeKilled = true; } itemEntity = (W3UsableItem)inv.GetItemEntityUnsafe( selectedItemId ); if ( itemEntity && m_useSelectedItemIfSpawned ) { // we have selected item and we are allowed to use it, so to it and kill itself. canTaskBeKilled = true; m_useSelectedItemIfSpawned = false; // reset flag ProcessUseSelectedItem( itemEntity, true ); } if ( canTaskBeKilled ) { KillWaitForItemSpawnAndProccesTask(); } } event OnBombProjectileReleased() { ResetRawPlayerHeading(); UnblockAction(EIAB_ThrowBomb, 'BombThrow'); UnblockAction(EIAB_Crossbow, 'BombThrow'); if(GetCurrentStateName() == 'AimThrow') PopState(); FactsAdd("ach_bomb", 1, 4 ); theGame.GetGamerProfile().CheckLearningTheRopes(); } public function SetIsThrowingItemWithAim(b : bool) { isThrowingItemWithAim = b; } public function SetIsThrowingItem( flag : bool ) {isThrowingItem = flag;} public function IsThrowingItem() : bool {return isThrowingItem;} public function IsThrowingItemWithAim() : bool {return isThrowingItemWithAim;} public function SetThrowHold(b : bool) {isThrowHoldPressed = b;} public function IsThrowHold() : bool {return isThrowHoldPressed;} public function SetIsAimingCrossbow( flag : bool ) {isAimingCrossbow = flag;} public function GetIsAimingCrossbow() : bool {return isAimingCrossbow;} event OnThrowAnimLeave() { var throwStage : EThrowStage; var thrownEntity : CThrowable; thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle ); if(thrownEntity && !thrownEntity.WasThrown()) { throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop); if(inv.IsItemBomb(selectedItemId)) { BombThrowCleanUp(); } else { ThrowingAbort(); } } thrownEntity = NULL; SetIsThrowingItem( false ); SetIsThrowingItemWithAim( false ); this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' ); UnblockAction(EIAB_ThrowBomb, 'BombThrow'); UnblockAction(EIAB_Crossbow, 'BombThrow'); } //Called when bomb throwing has started - it is ensured that we CAN throw it. At this point we don't know yet if it's a quick throw or aimed throw protected function BombThrowStart() { var slideTargetActor : CActor; BlockAction( EIAB_ThrowBomb, 'BombThrow' ); BlockAction(EIAB_Crossbow, 'BombThrow'); SetBehaviorVariable( 'throwStage', (int)TS_Start ); SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow ); if ( slideTarget ) { AddCustomOrientationTarget( OT_Actor, 'BombThrow' ); slideTargetActor = (CActor)( slideTarget ); //AK BOMB: moved rotation from anim event to scripts to prevent rotation to friendly and neutral npcs. // removed the check after commenting out ProcessCanAttackWhenNotInCombatBomb //if( !slideTargetActor || ( slideTargetActor && GetAttitudeBetween(this, slideTarget) == AIA_Hostile ) ) // SetCustomRotation( 'Throw', VecHeading( slideTarget.GetWorldPosition() - GetWorldPosition() ), 0.0f, 0.3f, false ); } else { if ( lastAxisInputIsMovement ) AddCustomOrientationTarget( OT_Actor, 'BombThrow' ); else AddCustomOrientationTarget( OT_Camera, 'BombThrow' ); } UpdateLookAtTarget(); SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.3f, false ); SetBehaviorVariable( 'itemType', (int)IT_Petard ); ProcessCanAttackWhenNotInCombatBomb(); if ( RaiseForceEvent('CombatAction') ) OnCombatActionStart(); //FIXME might be aborted afterwards and no bomb would be thrown actually theTelemetry.LogWithLabel(TE_FIGHT_HERO_THROWS_BOMB, inv.GetItemName( selectedItemId )); } //from animation event OnThrowAnimStart() { var itemId : SItemUniqueId; var thrownEntity : CThrowable; //Disable slots on radial menu this.radialSlots.Clear(); GetWitcherPlayer().GetItemEquippedOnSlot(EES_Petard1, itemId ); if( GetSelectedItemId() == itemId ) { this.radialSlots.PushBack( 'Slot2' ); } else { this.radialSlots.PushBack( 'Slot1' ); } this.radialSlots.PushBack( 'Slot3' ); this.radialSlots.PushBack( 'Slot4' ); this.radialSlots.PushBack( 'Slot5' ); this.EnableRadialSlotsWithSource( false, this.radialSlots, 'throwBomb' ); thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true ); thrownEntity.Initialize( this, selectedItemId ); EntityHandleSet( thrownEntityHandle, thrownEntity ); SetIsThrowingItem( true ); } public function BombThrowAbort() { BombThrowCleanUp(); UnblockAction( EIAB_ThrowBomb, 'BombThrow' ); UnblockAction(EIAB_Crossbow, 'BombThrow'); } private function BombThrowCleanUp() { var throwStage : EThrowStage; var thrownEntity : CThrowable; var vehicle : CVehicleComponent; thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle ); this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' ); throwStage = (int)GetBehaviorVariable( 'throwStage', (int)TS_Stop); SetBehaviorVariable( 'throwStage', (int)TS_Stop ); if( GetCurrentStateName() == 'AimThrow') { PopState(); thrownEntity.StopAiming( true ); } else if ( this.IsUsingHorse() ) { vehicle = (CVehicleComponent)(GetUsedVehicle().GetComponentByClassName('CVehicleComponent')); vehicle.GetUserCombatManager().OnForceItemActionAbort(); } //if bomb was not detached yet (is not flying) if(thrownEntity && !thrownEntity.WasThrown()) { thrownEntity.BreakAttachment(); thrownEntity.Destroy(); } thrownEntity = NULL; SetIsThrowingItem( false ); SetIsThrowingItemWithAim( false ); RemoveCustomOrientationTarget( 'BombThrow' ); } public function ProcessCanAttackWhenNotInCombatBomb() { /* //AK BOMB: keeping it just in case we need to bring it back var impactRange : float; var entities : array; var ent : CEntity; var actor : CActor; var petard : W3Petard; var vehicle : CEntity; var slotMatrix : Matrix; var isShootingFriendly : bool; if ( thrownEntity ) { petard = (W3Petard)( thrownEntity ); if ( !IsThreatened() ) { if ( this.playerAiming.GetCurrentStateName() == 'Aiming' ) ent = playerAiming.GetSweptFriendly(); else actor = (CActor)GetDisplayTarget(); if( ent || ( actor && actor.IsHuman() && !IsThreat( actor ) ) ) SetIsShootingFriendly( true ); else SetIsShootingFriendly( false ); } else SetIsShootingFriendly( false ); } else SetIsShootingFriendly( false ); */ SetIsShootingFriendly( false ); SetBehaviorVariable( 'isShootingFriendly', (float)( GetIsShootingFriendly() ) ); } public function SetIsShootingFriendly( flag : bool ) { isShootingFriendly = flag; } public function GetIsShootingFriendly() : bool { return isShootingFriendly; } //only for usable items protected function UsableItemStart() { var thrownEntity : CThrowable; //this seems like bullshit but it's because usable items use the same code as throwing bombs and shooting crossbow thrownEntity = (CThrowable)inv.GetDeploymentItemEntity( selectedItemId,,,true ); thrownEntity.Initialize( this, selectedItemId ); EntityHandleSet( thrownEntityHandle, thrownEntity ); SetBehaviorVariable( 'throwStage', (int)TS_Start ); SetIsThrowingItem( true ); SetBehaviorVariable( 'combatActionType', (int)CAT_ItemThrow ); if ( slideTarget ) { AddCustomOrientationTarget( OT_Actor, 'UsableItems' ); } else { if ( lastAxisInputIsMovement ) AddCustomOrientationTarget( OT_Actor, 'UsableItems' ); else AddCustomOrientationTarget( OT_Camera, 'UsableItems' ); } SetBehaviorVariable( 'itemType', (int)(-1) ); if ( RaiseForceEvent('CombatAction') ) OnCombatActionStart(); } protected function BombThrowRelease() { OnDelayOrientationChangeOff(); if ( GetIsShootingFriendly() ) BombThrowAbort(); else { SetBehaviorVariable( 'throwStage', (int)TS_End ); if ( playerAiming.GetCurrentStateName() == 'Aiming' ) SetCustomRotation( 'Throw', VecHeading( this.GetLookAtPosition() - GetWorldPosition() ), 0.0f, 0.2f, false ); } } protected function UsableItemRelease() { OnDelayOrientationChangeOff(); SetBehaviorVariable( 'throwStage', (int)TS_End ); RemoveCustomOrientationTarget( 'UsableItems' ); } // Called when usable item use or crossbow shot was aborted (bombs use different function) public function ThrowingAbort() { var thrownEntity : CThrowable; thrownEntity = (CThrowable)EntityHandleGet( thrownEntityHandle ); SetBehaviorVariable( 'throwStage', (int)TS_Stop ); RaiseEvent( 'actionStop' ); if( GetCurrentStateName() == 'AimThrow') { PopState(); thrownEntity.StopAiming( true ); } //if bomb was not detached yet (is not flying) if(thrownEntity && !thrownEntity.WasThrown()) { thrownEntity.BreakAttachment(); thrownEntity.Destroy(); } this.EnableRadialSlotsWithSource( true, this.radialSlots, 'throwBomb' ); } public function CanSetupCombatAction_Throw() : bool { //if has item selected if(!inv.IsIdValid( selectedItemId )) return false; //if not a throwable item if(!inv.IsItemSingletonItem(selectedItemId)) return false; //if input is not blocked if(!GetBIsInputAllowed()) return false; //if has ammo if(inv.GetItemQuantity(GetSelectedItemId()) <= 0 && !inv.ItemHasTag(selectedItemId, theGame.params.TAG_INFINITE_AMMO)) return false; //if action is not blocked or (HACK) we're in swimming if(!inputHandler.IsActionAllowed(EIAB_ThrowBomb) && GetCurrentStateName() != 'Swimming') return false; return true; } public function GetThrownEntity() : CThrowable { return (CThrowable)EntityHandleGet( thrownEntityHandle ); } // Crossbow events and functions event OnWeaponWait() { rangedWeapon.OnWeaponWait(); } event OnWeaponDrawStart() { rangedWeapon.OnWeaponDrawStart(); } event OnWeaponReloadStart() { rangedWeapon.OnWeaponReloadStart(); } event OnWeaponReloadEnd() { rangedWeapon.OnWeaponReloadEnd(); } event OnWeaponAimStart() { rangedWeapon.OnWeaponAimStart(); } event OnWeaponShootStart() { rangedWeapon.OnWeaponShootStart(); } event OnWeaponShootEnd() { rangedWeapon.OnWeaponShootEnd(); } event OnWeaponAimEnd() { rangedWeapon.OnWeaponAimEnd(); } event OnWeaponHolsterStart() { rangedWeapon.OnWeaponHolsterStart(); } event OnWeaponHolsterEnd() { rangedWeapon.OnWeaponHolsterEnd(); } event OnWeaponToNormalTransStart() { rangedWeapon.OnWeaponToNormalTransStart(); } event OnWeaponToNormalTransEnd() { rangedWeapon.OnWeaponToNormalTransEnd(); } event OnEnableAimingMode( enable : bool ) { if( !crossbowDontPopStateHack ) { if ( enable ) PushState( 'AimThrow' ); else if ( GetCurrentStateName() == 'AimThrow' ) PopState(); } } event OnRangedForceHolster( optional forceUpperBodyAnim, instant, dropItem : bool ) { if(rangedWeapon) rangedWeapon.OnForceHolster( forceUpperBodyAnim, instant, dropItem ); } public function IsCrossbowHeld() : bool { if (rangedWeapon) return rangedWeapon.GetCurrentStateName() != 'State_WeaponWait'; return false; } // Tickets event OnBlockAllCombatTickets( release : bool ) { if (!release ) ((CR4PlayerStateCombat)GetState('Combat')).OnBlockAllCombatTickets(false); } event OnForceTicketUpdate() {} //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @ATTACKS ///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /*script*/ event OnPocessActionPost(action : W3DamageAction) { var npc : CNewNPC; var attackAction : W3Action_Attack; var lifeLeech : float; super.OnPocessActionPost(action); attackAction = (W3Action_Attack)action; if(attackAction) { npc = (CNewNPC)action.victim; if(npc && npc.IsHuman() ) { PlayBattleCry('BattleCryHumansHit', 0.05f ); } else { PlayBattleCry('BattleCryMonstersHit', 0.05f ); } if(attackAction.IsActionMelee()) { //uninterrupted hits counting IncreaseUninterruptedHitsCount(); //camera shake // modXTFinishers BEGIN /* if( IsLightAttack( attackAction.GetAttackName() ) ) { GCameraShake(0.1, false, GetWorldPosition(), 10); } */ // modXTFinishers END //Caretaker Shovel life steal if(npc && inv.GetItemName(attackAction.GetWeaponId()) == 'PC Caretaker Shovel') { //inv.PlayItemEffect( items[i], 'stab_attack' ); lifeLeech = CalculateAttributeValue(inv.GetItemAttributeValue(attackAction.GetWeaponId() ,'lifesteal')); if (npc.UsesVitality()) lifeLeech *= action.processedDmg.vitalityDamage; else if (UsesEssence()) lifeLeech *= action.processedDmg.essenceDamage; else lifeLeech = 0; if ( lifeLeech > 0 ) { inv.PlayItemEffect( attackAction.GetWeaponId(), 'stab_attack' ); PlayEffect('drain_energy_caretaker_shovel'); GainStat(BCS_Vitality, lifeLeech); } } } } } public function SetHitReactTransScale(f : float) {hitReactTransScale = f;} public function GetHitReactTransScale() : float { if ( ( (CNewNPC)slideTarget ).GetIsTranslationScaled() ) return hitReactTransScale; else return 1.f; } //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @HORSE ///////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// public function GetHorseWithInventory() : CNewNPC { return (CNewNPC)EntityHandleGet( horseWithInventory ); } public function GetHorseCurrentlyMounted() : CNewNPC { return currentlyMountedHorse; } // Do not use outside of vehicle component public function _SetHorseCurrentlyMounted( horse : CNewNPC ) { currentlyMountedHorse = horse; } public function WasHorseRecentlySummoned() : bool { if ( horseSummonTimeStamp + 5.f > theGame.GetEngineTimeAsSeconds() ) return true; return false; } private const var MOUNT_DISTANCE_CBT : float; default MOUNT_DISTANCE_CBT = 3.0; private const var MOUNT_ANGLE_CBT : float; default MOUNT_ANGLE_CBT = 35.0; private const var MOUNT_ANGLE_EXP : float; default MOUNT_ANGLE_EXP = 45.0; public function IsMountingHorseAllowed( optional alwaysAllowedInExploration : bool ) : bool { var angle : float; var distance : float; if( IsInsideHorseInteraction() ) { angle = AngleDistance( thePlayer.rawPlayerHeading, VecHeading( thePlayer.horseInteractionSource.GetWorldPosition() - thePlayer.GetWorldPosition() ) ); if( thePlayer.IsInCombat() ) { if( AbsF( angle ) < MOUNT_ANGLE_CBT ) { distance = VecDistance( thePlayer.GetWorldPosition(), thePlayer.horseInteractionSource.GetWorldPosition() ); if( distance < MOUNT_DISTANCE_CBT ) { return true; } else { return false; } } else { return false; } } else { if( alwaysAllowedInExploration ) { return true; } else { if( AbsF( angle ) < MOUNT_ANGLE_EXP ) { return true; } else { return false; } } } } else { return false; } } public function FollowActor( actor : CActor ) { var l_aiTreeDecorator : CAIPlayerActionDecorator; var l_aiTree_onFoot : CAIFollowSideBySideAction; var l_aiTree_onHorse : CAIRiderFollowSideBySideAction; var l_success : bool = false; actor.AddTag( 'playerFollowing' ); if( thePlayer.IsUsingHorse() ) { l_aiTree_onHorse = new CAIRiderFollowSideBySideAction in this; l_aiTree_onHorse.OnCreated(); l_aiTree_onHorse.params.targetTag = 'playerFollowing'; } else { l_aiTree_onFoot = new CAIFollowSideBySideAction in this; l_aiTree_onFoot.OnCreated(); l_aiTree_onFoot.params.targetTag = 'playerFollowing'; } l_aiTreeDecorator = new CAIPlayerActionDecorator in this; l_aiTreeDecorator.OnCreated(); l_aiTreeDecorator.interruptOnInput = false; if( thePlayer.IsUsingHorse() ) l_aiTreeDecorator.scriptedAction = l_aiTree_onHorse; else l_aiTreeDecorator.scriptedAction = l_aiTree_onFoot; if( l_aiTreeDecorator ) l_success = ForceAIBehavior( l_aiTreeDecorator, BTAP_Emergency ); else if( thePlayer.IsUsingHorse() ) l_success = ForceAIBehavior( l_aiTree_onHorse, BTAP_Emergency ); else l_success = ForceAIBehavior( l_aiTree_onFoot, BTAP_Emergency ); if ( l_success ) { GetMovingAgentComponent().SetGameplayRelativeMoveSpeed( 0.0f ); } } public function SetCanFollowNpc( val : bool, actor : CActor ) { canFollowNpc = val; actorToFollow = actor; } public function CanFollowNpc() : bool { return canFollowNpc; } public function GetActorToFollow() : CActor { return actorToFollow; } /*public function SetIsFollowing( val : bool ) { isFollowing = val; if( val ) followingStartTime = theGame.GetEngineTimeAsSeconds(); else followingStartTime = 0.0; } public function GetFollowingStartTime() : float { return followingStartTime; } public function IsFollowing() : bool { return isFollowing; } timer function ResetIsFollowing( td : float, id : int ) { isFollowing = false; }*/ //////////////////////////////////////////////////////////////////////////////////////////// ///////////////////// @SWIMMING //////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// public function SetIsSwimming ( toggle : bool ) { if( isSwimming != toggle ) { thePlayer.substateManager.SetBehaviorParamBool( 'isSwimmingForOverlay', toggle ); isSwimming = toggle; } } //public function IsSwimming () : bool { return isSwimming; } //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @DURABILITY ////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// //returns true if repaired public function RepairItemUsingConsumable(item, consumable : SItemUniqueId) : bool { inv.SetItemDurabilityScript(item, inv.GetItemMaxDurability(item)); var curr, max, repairValue, itemValue, repairBonus, newDurability : float; //basic check if(!inv.IsIdValid(item) || !inv.IsIdValid(consumable) || !inv.HasItemDurability(item)) return false; curr = inv.GetItemDurability(item); max = inv.GetItemMaxDurability(item); //check durability level if(curr > max) return false; //check consumable type if( (inv.IsItemAnyArmor(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_ARMOR)) || (inv.IsItemSilverSwordUsableByPlayer(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_SILVER)) || (inv.IsItemSteelSwordUsableByPlayer(item) && inv.ItemHasTag(consumable, theGame.params.TAG_REPAIR_CONSUMABLE_STEEL)) ) { //item stats itemValue = CalculateAttributeValue(inv.GetItemAttributeValue(consumable, 'durabilityRepairValue')); if(itemValue <= 0) { LogAssert(false, "CR4Player.RepairItemUsingConsumable: consumable <<" + inv.GetItemName(consumable) + ">> has <=0 durabilityRepairValue!!!"); return false; } repairBonus = CalculateAttributeValue(inv.GetItemAttributeValue(consumable, 'durabilityBonusValue')); //calculate repairValue = max * itemValue /100; /* disabled repairing over 100% if(HasBookPerk(S_Book_28)) max = max * (1 + (repairBonus + perkValue) /100); */ newDurability = MinF(max, curr + repairValue); inv.SetItemDurabilityScript(item, newDurability); //consume return true; } { inv.RemoveItem(consumable); return true; } return false; } //////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @PushingObject ///////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /* event OnRigidBodyCollision( component : CComponent, actorIndex : int, shapeIndex : int ) { pushableComponent = component; if ( pushableComponent ) this.RaiseEvent('PushObject'); //component.ApplyForceAtPointToPhysicalObject } event OnRigidBodyExit( component : CComponent ) { this.RaiseEvent('PushObjectEnd'); pushableComponent = NULL; } event OnPushObjectStart() { moveAdj = GetMovingAgentComponent().GetMovementAdjustor(); moveAdj.CancelAll(); pushRotTicket = moveAdj.CreateNewRequest( 'RotateToObject' ); moveAdj.MaxRotationAdjustmentSpeed(pushRotTicket,30); moveAdj.Continuous(pushRotTicket); moveAdj.DontEnd(pushRotTicket); this.AddTimer('PushObjectUpdate',0.01,true, , , true); } event OnPushObjectStop() { this.RemoveTimer('PushObjectUpdate'); moveAdj.CancelByName('RotateToObject'); moveAdj = NULL; } timer function PushObjectUpdate( dt : float , id : int) { var impulse : Vector; moveAdj.RotateTo( pushRotTicket, rawPlayerHeading ); impulse = this.GetHeadingVector()*10.0; //impulse.Z += 0.5; //pushableComponent.ApplyLocalImpulseToPhysicalObject(impulse); } */ /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @DAY @NIGHT CYCLE CHECK ///////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// private function CheckDayNightCycle() { var time : GameTime; var isNight : bool; //if changed isNight = theGame.envMgr.IsNight(); if(prevDayNightIsNight != isNight) { if(isNight) OnNightStarted(); else OnDayStarted(); prevDayNightIsNight = isNight; } //schedule next call if(isNight) time = theGame.envMgr.GetGameTimeTillNextDay(); else time = theGame.envMgr.GetGameTimeTillNextNight(); AddGameTimeTimer('DayNightCycle', time); } timer function DayNightCycle(dt : GameTime, id : int) { CheckDayNightCycle(); } /*script*/ event OnNightStarted() { var pam : W3PlayerAbilityManager; if(CanUseSkill(S_Perk_01)) { pam = (W3PlayerAbilityManager)abilityManager; pam.SetPerk01Abilities(false, true); } } /*script*/ event OnDayStarted() { var pam : W3PlayerAbilityManager; if(CanUseSkill(S_Perk_01)) { pam = (W3PlayerAbilityManager)abilityManager; pam.SetPerk01Abilities(true, false); } } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @INPUT ////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public function ForceUnlockAllInputActions(alsoQuestLocks : bool) { if ( inputHandler ) inputHandler.ForceUnlockAllInputActions(alsoQuestLocks); } public function SetPrevRawLeftJoyRot() { prevRawLeftJoyRot = rawLeftJoyRot; } public function GetPrevRawLeftJoyRot() : float { return prevRawLeftJoyRot; } public function GetExplorationInputContext() : name { return explorationInputContext; } public function GetCombatInputContext() : name { return combatInputContext; } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @EXPLORATION //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public function SetIsOnBoat(b : bool) { isOnBoat = b; } public function IsOnBoat() : bool { return isOnBoat; } public function IsInShallowWater() : bool { return isInShallowWater; } event OnEnterShallowWater() { if ( isInShallowWater ) return false; isInShallowWater = true; BlockAction( EIAB_Dodge,'ShallowWater', false, false, true ); BlockAction( EIAB_Sprint,'ShallowWater', false, false, true ); BlockAction( EIAB_Crossbow,'ShallowWater', false, false, true ); BlockAction( EIAB_Jump,'ShallowWater', false, false, true ); SetBehaviorVariable( 'shallowWater',1.0); } event OnExitShallowWater() { if ( !isInShallowWater ) return false; isInShallowWater = false; BlockAllActions('ShallowWater',false); SetBehaviorVariable( 'shallowWater',0.0); } public function TestIsInSettlement() : bool { return IsInSettlement(); } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// GLOSSARY //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// //Processes glossary image filename and exchanges it with override if provided public function ProcessGlossaryImageOverride( defaultImage : string, uniqueTag : name ) : string { var size : int; var i : int; size = glossaryImageOverride.Size(); if( size == 0 ) return defaultImage; for( i = 0; i < size; i += 1 ) { if( glossaryImageOverride[i].uniqueTag == uniqueTag ) return glossaryImageOverride[i].imageFileName; } return defaultImage; } //Adds glossary image override filename to array public function EnableGlossaryImageOverride( uniqueTag : name, imageFileName : string, enable : bool ) { var imageData : SGlossaryImageOverride; var size : int; var i : int; for( i = 0; i < glossaryImageOverride.Size(); i += 1 ) { if( glossaryImageOverride[i].uniqueTag == uniqueTag ) { glossaryImageOverride.Remove(glossaryImageOverride[i]); } } if( enable ) { if( IsNameValid(uniqueTag) && imageFileName != "" ) { glossaryImageOverride.PushBack( SGlossaryImageOverride( uniqueTag, imageFileName ) ); } } } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// MONSTER HUNT INVESTIGATION AREAS ///////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public function SetCurrentMonsterHuntInvestigationArea ( area : W3MonsterHuntInvestigationArea ) { currentMonsterHuntInvestigationArea = area; } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// BARBER SYSTEM CUSTOM HEAD ///////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public function RememberCustomHead( headName : name ) { rememberedCustomHead = headName; } public function GetRememberedCustomHead() : name { return rememberedCustomHead; } public function ClearRememberedCustomHead() { rememberedCustomHead = ''; } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @TUTORIAL //////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// public function CreateTutorialInput() { var prevInputHandler : CPlayerInput; prevInputHandler = inputHandler; inputHandler = new W3PlayerTutorialInput in this; inputHandler.Initialize(false, prevInputHandler); if(prevInputHandler) delete prevInputHandler; } public function CreateInput() { var oldInputHandler : CPlayerInput; oldInputHandler = inputHandler; inputHandler = new CPlayerInput in this; inputHandler.Initialize(false, oldInputHandler); } timer function TutorialSilverCombat(dt : float, id : int) { var i : int; var actors : array; if(IsInCombat()) { actors = GetNPCsAndPlayersInRange(20, 1000000, ,FLAG_ExcludePlayer + FLAG_OnlyAliveActors); for(i=0; i { if(actors[i] && IsRequiredAttitudeBetween(this, actors[i], true) && actors[i].UsesEssence()) { FactsAdd("TutorialShowSilver"); RemoveTimer('TutorialSilverCombat'); break; } } } } private saved var m_bossTag : name; public function GetBossTag() : name { return m_bossTag; } public function SetBossTag( bossTag : name ) { m_bossTag = bossTag; } private saved var m_usingCoatOfArms : bool; default m_usingCoatOfArms = false; public function IsUsingCoatOfArms() : bool { return m_usingCoatOfArms; } public function SetUsingCoatOfArms( using : bool) { m_usingCoatOfArms = using; } private saved var m_initialTimeOut : float; private saved var m_currentTimeOut : float; public function GetInitialTimeOut() : float { return m_initialTimeOut; } public function SetInitialTimeOut( timeOut : float ) { m_initialTimeOut = timeOut; } public function GetCurrentTimeOut() : float { return m_currentTimeOut; } public function SetCurrentTimeOut( timeOut : float ) { m_currentTimeOut = timeOut; } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @FINISHERS //////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// timer function DelayedFinisherInputTimer(dt : float, id : int) { //theGame.SetTimeScale( 0.1, theGame.GetTimescaleSource(ETS_FinisherInput), theGame.GetTimescalePriority(ETS_FinisherInput) ); //GetFinisherVictim().EnableFinishComponent( true ); } timer function RemoveFinisherCameraAnimationCheck(dt : float, id : int) { if ( !isInFinisher && !bLAxisReleased ) { theGame.GetSyncAnimManager().OnRemoveFinisherCameraAnimation(); RemoveTimer( 'RemoveFinisherCameraAnimationCheck' ); } } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// @DEBUG @TIMERS //////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// timer function GameplayFactRemove(dt : float, timerId : int) { theGame.GameplayFactRemoveFromTimer(timerId); } //gives NORMAL starting inventory timer function GiveStartingItems(dt : float, timerId : int) { var template : CEntityTemplate; var invEntity : CInventoryComponent; var entity : CEntity; var items : array; var id : SItemUniqueId; var i : int; //wait for inventory to init if(inv) { inv.GetAllItems(items); if(items.Size() <= 0) { return; } } else { return; } //add items template = (CEntityTemplate)LoadResource("geralt_inventory_release"); entity = theGame.CreateEntity(template, Vector(0,0,0)); invEntity = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent'); invEntity.GetAllItems(items); for(i=0; i { id = invEntity.GiveItemTo(inv, items[i], 0, false, true); if ( inv.ItemHasTag(id,'Scabbard') ) { inv.MountItem(id); } else if(!inv.IsItemFists(id) && inv.GetItemName(id) != 'Cat 1') //hack for cat potion - don't equip! { EquipItem(id); } else if(inv.IsItemSingletonItem(id)) { inv.SingletonItemSetAmmo(id, inv.SingletonItemGetMaxAmmo(id)); } } entity.Destroy(); //remove timer RemoveTimer('GiveStartingItems'); } //Adds items used for testing. Won't be called in final release. Items are added from geralt_inventory entity. //Works as a timer since we need to wait for inventory to init and there is no such event. timer function Debug_GiveTestingItems(dt : float, optional id : int) { var template : CEntityTemplate; var invTesting : CInventoryComponent; var entity : CEntity; var items : array; var i : int; var slot : EEquipmentSlots; //wait for inventory to init if(inv) { inv.GetAllItems(items); if(items.Size() <= 0) { return; } } else { return; } template = (CEntityTemplate)LoadResource("geralt_inventory_internal"); entity = theGame.CreateEntity(template, Vector(0,0,0)); invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent'); invTesting.GiveAllItemsTo(inv, true); entity.Destroy(); //once called remove the timer RemoveTimer('Debug_GiveTestingItems'); //equip crossbow, bombs and bolts, select bolts inv.GetAllItems(items); for(i=0; i { if( inv.IsItemCrossbow(items[i]) || inv.IsItemBomb(items[i]) ) { slot = inv.GetSlotForItemId(items[i]); EquipItem(items[i], slot); if( (W3PlayerWitcher)this && inv.IsItemCrossbow(items[i]) ) GetWitcherPlayer().SelectQuickslotItem(slot); } else if(inv.IsItemBolt(items[i])) { slot = inv.GetSlotForItemId(items[i]); EquipItem(items[i], slot); } if(inv.IsItemSingletonItem(items[i])) { inv.SingletonItemSetAmmo(items[i], inv.SingletonItemGetMaxAmmo(items[i])); } } } //called in tutorial in not final version to remove testing items timer function Debug_RemoveTestingItems(dt : float, id : int) { var template : CEntityTemplate; var entity : CEntity; var invTesting : CInventoryComponent; var ids : array; var i : int; template = (CEntityTemplate)LoadResource("geralt_inventory_internal"); entity = theGame.CreateEntity(template, Vector(0,0,0)); invTesting = (CInventoryComponent)entity.GetComponentByClassName('CInventoryComponent'); invTesting.GetAllItems(ids); for(i=0; i inv.RemoveItemByName(invTesting.GetItemName(ids[i]), invTesting.GetItemQuantity(ids[i])); entity.Destroy(); RemoveTimer('Debug_RemoveTestingItems'); } timer function Debug_DelayedConsoleCommand(dt : float, id : int) { //inv.AddAnItem('Recipe for Mutagen 23'); inv.AddAnItem('Boots 2 schematic'); } function DBG_SkillSlots() { ((W3PlayerAbilityManager)abilityManager).DBG_SkillSlots(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// @BACKLIGHT COLOR //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public final function SetPadBacklightColor(r, g, b : int) { var padBacklightColor : Vector; padBacklightColor.X = r / 255; padBacklightColor.Y = g / 255; padBacklightColor.Z = b / 255; SetBacklightColor(padBacklightColor); } public final function SetPadBacklightColorFromSign(signType : ESignType) { LogPS4Light("SetPadBacklightColorFromSign... " + signType); switch(signType) { case ST_Yrden: SetPadBacklightColor( 200 , 81 , 255 ); break; // Violet case ST_Quen: SetPadBacklightColor( 255 , 205 , 68 ); break; // Yellow case ST_Igni: SetPadBacklightColor( 255 , 79 , 10 ); break; // Orange case ST_Axii: SetPadBacklightColor( 255 , 255 , 255 ); break; // White case ST_Aard: SetPadBacklightColor( 158 , 214 , 255 ); break; // Blue } } timer function ResetPadBacklightColorTimer(dt : float, id : int) { ResetPadBacklightColor(); } public final function ResetPadBacklightColor(optional skipHeldWeapon : bool) { var weapons : array; var sword : CWitcherSword; var healthPercentage : float; var tmpBacklight : Vector; if(!skipHeldWeapon) { weapons = inv.GetHeldWeapons(); //if holding a sword the default backlight color matches the one set in sword entity if(weapons.Size() > 0) { sword = (CWitcherSword)inv.GetItemEntityUnsafe(weapons[0]); if(sword) { tmpBacklight.X = sword.padBacklightColor.X / 255.0f; tmpBacklight.Y = sword.padBacklightColor.Y / 255.0f; tmpBacklight.Z = sword.padBacklightColor.Z / 255.0f; tmpBacklight.W = 1.0f; SetBacklightColor( tmpBacklight ); LogPS4Light("Setting light from sword template: " + NoTrailZeros(sword.padBacklightColor.X) + ", " + NoTrailZeros(sword.padBacklightColor.Y) + ", " + NoTrailZeros(sword.padBacklightColor.Z) ); return; } } } healthPercentage = GetStatPercents( BCS_Vitality ); SetBacklightFromHealth( healthPercentage ); LogPS4Light("Setting light from health, " + NoTrailZeros(RoundMath(healthPercentage*100)) + "%"); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// event OnOpenningDoor() { if( !thePlayer.IsUsingHorse() ) RaiseEvent('OpenDoor'); } public var loopingCameraShakeAnimName : name; timer function RemoveQuestCameraShakeTimer( dt : float , id : int) { RemoveQuestCameraShake( loopingCameraShakeAnimName ); } public function RemoveQuestCameraShake( animName : name ) { var camera : CCustomCamera = theGame.GetGameCamera(); var animation : SCameraAnimationDefinition; camera.StopAnimation( animName ); } public function GetCameraPadding() : float { if( theGame.IsFocusModeActive() ) { return 0.25; // Tweaked for [108933] Geralt is being clipped when using focus mode while running towards camera. } else { return 0.02f; // Tweaked for [114907] Player dissolving while aiming crossbow. } } public function IsPerformingPhaseChangeAnimation() : bool { return isPerformingPhaseChangeAnimation; } public function SetIsPerformingPhaseChangeAnimation( val : bool ) { isPerformingPhaseChangeAnimation = val; } private function DealCounterDamageToOlgierd() { var damage : W3DamageAction; damage = new W3DamageAction in this; damage.Initialize( thePlayer.GetTarget(), thePlayer.GetTarget(), NULL, this, EHRT_None, CPS_Undefined, false, false, false, true ); damage.AddDamage( theGame.params.DAMAGE_NAME_DIRECT, thePlayer.GetTarget().GetStatMax( BCS_Vitality ) * 3 / 100 ); theGame.damageMgr.ProcessAction( damage ); delete damage; } timer function PlayDelayedCounterDamageEffect( dt : float, id : int ) { thePlayer.GetTarget().PlayEffect( 'olgierd_energy_blast' ); } // TEST public function SetTestAdjustRequestedMovementDirection( val : bool ) { testAdjustRequestedMovementDirection = val; } event OnVisualDebug( frame : CScriptedRenderFrame, flag : EShowFlags ) { var boneFollow : int; var bonePosition : Vector; var yrdenEntity : W3YrdenEntity; substateManager.OnVisualDebug( frame, flag ); boneFollow = thePlayer.GetBoneIndex( 'Reference' ); bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) ); frame.DrawText( "R", bonePosition, Color( 50, 200, 70 ) ); //frame.DrawText( "R", bonePositionCam, Color( 200, 50, 70 ) ); boneFollow = thePlayer.GetBoneIndex( 'Trajectory' ); bonePosition = MatrixGetTranslation( thePlayer.GetBoneWorldMatrixByIndex( boneFollow ) ); frame.DrawSphere( bonePosition, 0.1f, Color( 200, 50, 70 ) ); frame.DrawText( "T", bonePosition, Color( 200, 50, 70 ) ); //frame.DrawSphere( lastSafePosition, 1.0f, Color( 50, 200, 70 ) ); //frame.DrawText( "SavePos", lastSafePosition, Color( 50, 200, 70 ) ); yrdenEntity = (W3YrdenEntity)GetWitcherPlayer().GetSignEntity(ST_Yrden); yrdenEntity.OnVisualDebug(frame, flag, false); return true; } timer function PotDrinkTimer(dt : float, id : int) { inputHandler.PotDrinkTimer(false); } public function SetIsHorseRacing( val : bool ) { isHorseRacing = val; } public function GetIsHorseRacing() : bool { return isHorseRacing; } public function SetHorseCombatSlowMo( val : bool ) { horseCombatSlowMo = val; } public function GetHorseCombatSlowMo() : bool { return horseCombatSlowMo; } public function SetItemsPerLevelGiven( id : int ) { itemsPerLevelGiven[id] = true; } private function AddItemPerLevelList() { var i : int; itemsPerLevel.Clear(); itemsPerLevel.PushBack('O'); itemsPerLevel.PushBack('No Mans Land sword 2'); itemsPerLevel.PushBack('No Mans Land sword 3'); itemsPerLevel.PushBack('Silver sword 2'); itemsPerLevel.PushBack('Boots 01'); itemsPerLevel.PushBack('Novigraadan sword 2'); itemsPerLevel.PushBack('Light armor 01'); itemsPerLevel.PushBack('Heavy boots 01'); itemsPerLevel.PushBack('Nilfgaardian sword 3'); itemsPerLevel.PushBack('Silver sword 3'); itemsPerLevel.PushBack('Heavy gloves 01'); itemsPerLevel.PushBack('Skellige sword 2'); itemsPerLevel.PushBack('Heavy pants 01'); itemsPerLevel.PushBack('Silver sword 4'); itemsPerLevel.PushBack('No Mans Land sword 4'); itemsPerLevel.PushBack('Heavy armor 01'); itemsPerLevel.PushBack('Heavy boots 02'); itemsPerLevel.PushBack('Skellige sword 3'); itemsPerLevel.PushBack('Silver sword 5'); itemsPerLevel.PushBack('Heavy pants 02'); itemsPerLevel.PushBack('Heavy gloves 02'); itemsPerLevel.PushBack('Heavy gloves 02'); itemsPerLevel.PushBack('Heavy armor 02'); itemsPerLevel.PushBack('Scoiatael sword 1'); if ( itemsPerLevelGiven.Size() < 49 ) { itemsPerLevelGiven.Clear(); for (i = 0; i < itemsPerLevel.Size(); i += 1) { itemsPerLevelGiven.PushBack( false ); } } } // TEMP public function DealDamageToBoat( dmg : float, index : int, optional globalHitPos : Vector ) { var boat : CBoatDestructionComponent; if(usedVehicle) { boat = (CBoatDestructionComponent) usedVehicle.GetComponentByClassName( 'CBoatDestructionComponent' ); if( boat ) { boat.DealDamage( dmg, index, globalHitPos ); } } } //////////////////////////////////////////////////////////////////////////////// // // PLAYABLE AREA // public function OnStartTeleportingPlayerToPlayableArea() { var FADEOUT_INTERVAL : float = 0.5; // if we jumped on horse right before being teleported, we need to disable falling damage because height difference may kill us if ( thePlayer.IsUsingHorse() ) { if ( thePlayer.GetUsedHorseComponent().OnCheckHorseJump() ) { thePlayer.GetUsedHorseComponent().SetCanTakeDamageFromFalling( false ); } } if ( thePlayer.IsActionAllowed( EIAB_FastTravel ) ) { OnOpenMapToLetPlayerGoBackToPlayableArea(); } else { theGame.FadeOutAsync( FADEOUT_INTERVAL ); thePlayer.AddTimer( 'BorderTeleportFadeOutTimer', FADEOUT_INTERVAL, false ); } } timer function BorderTeleportFadeOutTimer( dt : float, id : int ) { OnTeleportPlayerToPlayableArea( false ); } public function OnOpenMapToLetPlayerGoBackToPlayableArea() { var initData : W3MapInitData; initData = new W3MapInitData in this; initData.SetTriggeredExitEntity( true ); initData.ignoreSaveSystem = true; initData.setDefaultState('FastTravel'); theGame.RequestMenuWithBackground( 'MapMenu', 'CommonMenu', initData ); } public function OnTeleportPlayerToPlayableArea( afterClosingMap : bool ) { var BLACKSCREEN_INTERVAL : float = 0.5; var manager : CCommonMapManager = theGame.GetCommonMapManager(); theGame.FadeOutAsync( 0 ); thePlayer.TeleportWithRotation( manager.GetBorderTeleportPosition(), manager.GetBorderTeleportRotation() ); thePlayer.AddTimer( 'BorderTeleportFadeInTimer', BLACKSCREEN_INTERVAL, false ); } timer function BorderTeleportFadeInTimer( dt : float, id : int ) { var FADEIN_INTERVAL : float = 0.5; theGame.FadeInAsync( FADEIN_INTERVAL ); } public final function SetLastInstantKillTime(g : GameTime) { lastInstantKillTime = g; } // // // //////////////////////////////////////////////////////////////////////////////// timer function TestTimer(dt : float, id : int ) { LogChannel('asdf', "asdf"); theGame.FadeOutAsync( 5 ); } public final function Debug_ReleaseCriticalStateSaveLocks() { effectManager.Debug_ReleaseCriticalStateSaveLocks(); } timer function Debug_SpamSpeed(dt : float, id : int) { if(currentlyMountedHorse) { LogSpeed("curr player's horse speed: " + NoTrailZeros(currentlyMountedHorse.GetMovingAgentComponent().GetSpeed())) ; } else { LogSpeed("curr player speed: " + NoTrailZeros(GetMovingAgentComponent().GetSpeed())) ; } } timer function RemoveInstantKillSloMo(dt : float, id : int) { theGame.RemoveTimeScale( theGame.GetTimescaleSource(ETS_InstantKill) ); } // modXTFinishers BEGIN timer function XTFinishersSlowdownTimerCallback(dt : float, id : int) { ((XTFinishersAbstractSlowdownManager)theGame.xtFinishersMgr.slowdownMgr).EndSlowdownSegment(true); } // modXTFinishers END timer function RemoveForceFinisher(dt : float, id : int) { forceFinisher = false; } public final function Debug_ClearAllActionLocks(optional action : EInputActionBlock, optional all : bool) { inputHandler.Debug_ClearAllActionLocks(action, all); } function OnFocusedCameraBlendBegin() {} function OnFocusedCameraBlendUpdate( progress : float ) {} function OnFocusedCameraBlendEnd() {} public function GetEtherealCount() : int { return etherealCount; } public function IncrementEtherealCount() { etherealCount += 1; if( etherealCount == 6 ) ResetEtherealCount(); } public function ResetEtherealCount() { etherealCount = 0; } // PHANTOM WEAPON //------------------------------------------------------------------------------------------------------------------ public function InitPhantomWeaponMgr() { if( !phantomWeaponMgr ) { phantomWeaponMgr = new CPhantomWeaponManager in this; phantomWeaponMgr.Init( this.GetInventory() ); } } public function DestroyPhantomWeaponMgr() { if( phantomWeaponMgr ) { delete phantomWeaponMgr; } } public function GetPhantomWeaponMgr() : CPhantomWeaponManager { if( phantomWeaponMgr ) { return phantomWeaponMgr; } else { return NULL; } } public timer function DischargeWeaponAfter( td : float, id : int ) { GetPhantomWeaponMgr().DischargeWeapon(); } //------------------------------------------------------------------------------------------------------------------ exec function ttt() { thePlayer.AddTimer( 'TestTimer', 5, false ); } [/spoiler]();>();>();>();>;>;>();>();>();>();>();>();>();>();>();>();>();>();>();>();> Link to comment Share on other sites More sharing options...
sharksbull Posted May 28, 2017 Share Posted May 28, 2017 (edited) versão 1.21 Ola me ajudem, esta dando esse erro Erro [content0] game \ gameplay \ focus \ focus.ws (202): A função 'LogWithName' não tem 1 param (s) Erro [content0] game \ gameplay \ focus \ focus.ws (262): Função 'LogWithName' não leva 1 param (s) Erro [content0] game \ gui \ menus \ gwintgamemenu.ws (105): A função 'LogWithName' não tem 1 param (s) (44): Função 'LogWithName' não leva 1 param (s) (56): Função 'LogWithName' não leva 1 parâmetro (s) Erro [content0] game \ player \ states \ playerdialogstate.ws (46): A função 'LogWithName' não tem 1 param (s) Erro [content0] game \ player \ states \ aimthrow.ws (39): A função 'LogWithName' não tem 1 param (s) Erro [content0] game \ player \ states \ combat.ws (123): Função 'LogWithName' não tem 1 param (s) Erro [content0] game \ player \ states \ exploration.ws (55): A função 'LogWithName' não tem 1 param (s) Erro [content0] game \ player \ states \ swimming.ws (247): Função 'LogWithName' não leva 1 param (s) Aviso [content0] engine \ telemetrykeyword.ws (5): A função nativa 'Log' não foi exportada da classe 'CR4TelemetryScriptProxy' no código C ++. Warning [content0] engine \ environment.ws (25): A função nativa global 'EnableDebugOverlayFilter' não foi exportada do código C ++. Warning [content0] engine \ environment.ws (27): A função nativa global 'EnableDebugPostProcess' não foi exportada do código C ++. Aviso [content0] engine \ showflags.ws (9): A função nativa global 'DebugSetEShowFlag' não foi exportada do código C ++. Edited May 28, 2017 by sharksbull Link to comment Share on other sites More sharing options...
Recommended Posts