Gambit77 Posted November 6, 2015 Share Posted November 6, 2015 When I try launching the game I'm getting an error at the Compiling Scripts file parsing 1347/1388 mark.This is the error message I'm getting, and I'm not sure why because the file doesn't end at line 8. Error [mod0000_mergedfiles]game\player\playerwitcher.ws(7901): Unexpected end of file found after '{' at line 8v Here's the text from that file /***********************************************************************/ /***********************************************************************/ /** Copyright © 2009-2014 /** Author : collective mind of the CDP /***********************************************************************/ statemachine class W3PlayerWitcher extends CR4Player { //---=== modFriendlyHUD ===--- var foundCampFire : bool; var campFireEnt : CGameplayEntity; //---=== modFriendlyHUD ===--- //CRAFTING private saved var craftingSchematics : array<name>; //known crafting schematics //ALCHEMY private saved var alchemyRecipes : array<name>; //known alchemy recipes // SKILLS private var levelupAbilities : array< name >; private var fastAttackCounter, heavyAttackCounter : int; //counter for light/heavy attacks. Currently not used but I leave it in case it will come back private var isInFrenzy : bool; private var hasRecentlyCountered : bool; private saved var cannotUseUndyingSkill : bool; //if activation delay of Undying skill has finished or not // FOCUS MODE public var canSwitchFocusModeTarget : bool; protected var switchFocusModeTargetAllowed : bool; default canSwitchFocusModeTarget = true; default switchFocusModeTargetAllowed = true; // SIGNS 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<W3YrdenEntity>; default equippedSign = ST_Aard; //COMBAT MECHANICS //private var combatStance : EPlayerCombatStance; private var bDispalyHeavyAttackIndicator : bool; //#B private var bDisplayHeavyAttackFirstLevelTimer : bool; //#B public var specialAttackHeavyAllowed : bool; default bIsCombatActionAllowed = true; default bDispalyHeavyAttackIndicator = false; //#B default bDisplayHeavyAttackFirstLevelTimer = true; //#B //INPUT default explorationInputContext = 'Exploration'; default combatInputContext = 'Combat'; default combatFistsInputContext = 'Combat'; // COMPANION MODULE private saved var companionNPCTag : name; private saved var companionNPCTag2 : name; private saved var companionNPCIconPath : string; private saved var companionNPCIconPath2 : string; //ITEMS private saved var itemSlots : array<SItemUniqueId>; private var remainingBombThrowDelaySlot1 : float; private var remainingBombThrowDelaySlot2 : float; private var previouslyUsedBolt : SItemUniqueId; //ID of previously used special bolt (before we entered water) default isThrowingItem = false; default remainingBombThrowDelaySlot1 = 0.f; default remainingBombThrowDelaySlot2 = 0.f; //---------------------------- //SKILLS //---------------------------- private var tempLearnedSignSkills : array<SSimpleSkill>; //list of skills temporarily added for the duration of 'All Out' skill (sword_s19) public saved var autoLevel : bool; //temp flag for switching autoleveling for player //--------------------------------------------------------- //POTIONS and TOXICITY //--------------------------------------------------------- protected var skillBonusPotionEffect : CBaseGameplayEffect; //cached current bonus potion effect (for skill) - we can have only one //CHARACTER LEVELING AND DEVELOPMENT public saved var levelManager : W3LevelManager; //REPUTATION saved var reputationManager : W3Reputation; //MEDALLION private editable var medallionEntity : CEntityTemplate; private var medallionController : W3MedallionController; //#B Radial Menu public var bShowRadialMenu : bool; private var _HoldBeforeOpenRadialMenuTime : float; default _HoldBeforeOpenRadialMenuTime = 0.5f; public var MappinToHighlight : array<SHighlightMappin>; //OTHER protected saved var horseManagerHandle : EntityHandle; //handles horse stuff //#DynSave this is always dynamic and will never be saved, can't fix private var isInitialized : bool; default isInitialized = false; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //AMM var vAMM : CAMM; //AMM //////////////////////////////////////////////////////////////////////////////// // // INITIALIZATION // //////////////////////////////////////////////////////////////////////////////// event OnSpawned( spawnData : SEntitySpawnData ) { var i : int; var items : array<SItemUniqueId>; var items2 : array<SItemUniqueId>; 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' ); theTelemetry.Log( TE_HERO_SPAWNED ); runewordInfusionType = ST_None; // Ability manager recalculates resistances so we need to re-equip items first inv = GetInventory(); //inv is set in super // create and initialize sign owner signOwner = new W3SignOwnerPlayer in this; signOwner.Init( this ); itemSlots.Resize( EnumGetMax('EEquipmentSlots')+1 ); if(!spawnData.restored) { levelManager = new W3LevelManager in this; levelManager.Initialize(); //equip items mounted by default from character template inv.GetAllItems(items); for(i=0; i<items.Size(); i+=1) { if(inv.IsItemMounted(items[i]) && ( !inv.IsItemBody(items[i]) || inv.GetItemCategory(items[i]) == 'hair' ) ) EquipItem(items[i]); } //Sets up default Geralt hair item //SetupStartingHair(); // Add starting alchemy recipes 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); // CRAFTING ITEM SCHEMATICS AddStartingSchematics(); } else { AddTimer('DelayedOnItemMount', 0.1, true); //Check applied hair for any errors that might occur due to item manipulation via scripts CheckHairItem(); } super.OnSpawned( spawnData ); // New mutagen recipes, added here to work with old saves 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); levelupAbilities.PushBack('Lvl1'); levelupAbilities.PushBack('Lvl1'); levelupAbilities.PushBack('Lvl2'); levelupAbilities.PushBack('Lvl3'); levelupAbilities.PushBack('Lvl4'); levelupAbilities.PushBack('Lvl5'); levelupAbilities.PushBack('Lvl6'); levelupAbilities.PushBack('Lvl7'); levelupAbilities.PushBack('Lvl8'); levelupAbilities.PushBack('Lvl9'); levelupAbilities.PushBack('Lvl10'); levelupAbilities.PushBack('Lvl11'); levelupAbilities.PushBack('Lvl12'); levelupAbilities.PushBack('Lvl13'); levelupAbilities.PushBack('Lvl14'); levelupAbilities.PushBack('Lvl15'); levelupAbilities.PushBack('Lvl16'); levelupAbilities.PushBack('Lvl17'); levelupAbilities.PushBack('Lvl18'); levelupAbilities.PushBack('Lvl19'); levelupAbilities.PushBack('Lvl20'); levelupAbilities.PushBack('Lvl21'); levelupAbilities.PushBack('Lvl22'); levelupAbilities.PushBack('Lvl23'); levelupAbilities.PushBack('Lvl24'); levelupAbilities.PushBack('Lvl25'); levelupAbilities.PushBack('Lvl26'); levelupAbilities.PushBack('Lvl27'); levelupAbilities.PushBack('Lvl28'); levelupAbilities.PushBack('Lvl29'); levelupAbilities.PushBack('Lvl30'); levelupAbilities.PushBack('Lvl31'); levelupAbilities.PushBack('Lvl32'); levelupAbilities.PushBack('Lvl33'); levelupAbilities.PushBack('Lvl34'); levelupAbilities.PushBack('Lvl35'); levelupAbilities.PushBack('Lvl36'); levelupAbilities.PushBack('Lvl37'); levelupAbilities.PushBack('Lvl38'); levelupAbilities.PushBack('Lvl39'); levelupAbilities.PushBack('Lvl40'); levelupAbilities.PushBack('Lvl41'); levelupAbilities.PushBack('Lvl42'); levelupAbilities.PushBack('Lvl43'); levelupAbilities.PushBack('Lvl44'); levelupAbilities.PushBack('Lvl45'); levelupAbilities.PushBack('Lvl46'); levelupAbilities.PushBack('Lvl47'); levelupAbilities.PushBack('Lvl48'); levelupAbilities.PushBack('Lvl49'); levelupAbilities.PushBack('Lvl50'); levelupAbilities.PushBack('Lvl51'); levelupAbilities.PushBack('Lvl52'); levelupAbilities.PushBack('Lvl53'); levelupAbilities.PushBack('Lvl54'); levelupAbilities.PushBack('Lvl55'); levelupAbilities.PushBack('Lvl56'); levelupAbilities.PushBack('Lvl57'); levelupAbilities.PushBack('Lvl58'); levelupAbilities.PushBack('Lvl59'); levelupAbilities.PushBack('Lvl60'); levelupAbilities.PushBack('Lvl61'); levelupAbilities.PushBack('Lvl62'); levelupAbilities.PushBack('Lvl63'); levelupAbilities.PushBack('Lvl64'); levelupAbilities.PushBack('Lvl65'); levelupAbilities.PushBack('Lvl66'); levelupAbilities.PushBack('Lvl67'); levelupAbilities.PushBack('Lvl68'); levelupAbilities.PushBack('Lvl69'); levelupAbilities.PushBack('Lvl70'); levelupAbilities.PushBack('Lvl71'); levelupAbilities.PushBack('Lvl72'); levelupAbilities.PushBack('Lvl73'); levelupAbilities.PushBack('Lvl74'); levelupAbilities.PushBack('Lvl75'); levelupAbilities.PushBack('Lvl76'); levelupAbilities.PushBack('Lvl77'); levelupAbilities.PushBack('Lvl78'); levelupAbilities.PushBack('Lvl79'); levelupAbilities.PushBack('Lvl80'); levelupAbilities.PushBack('Lvl81'); levelupAbilities.PushBack('Lvl82'); levelupAbilities.PushBack('Lvl83'); levelupAbilities.PushBack('Lvl84'); levelupAbilities.PushBack('Lvl85'); levelupAbilities.PushBack('Lvl86'); levelupAbilities.PushBack('Lvl87'); levelupAbilities.PushBack('Lvl88'); levelupAbilities.PushBack('Lvl89'); levelupAbilities.PushBack('Lvl90'); levelupAbilities.PushBack('Lvl91'); levelupAbilities.PushBack('Lvl92'); levelupAbilities.PushBack('Lvl93'); levelupAbilities.PushBack('Lvl94'); levelupAbilities.PushBack('Lvl95'); levelupAbilities.PushBack('Lvl96'); levelupAbilities.PushBack('Lvl97'); levelupAbilities.PushBack('Lvl98'); levelupAbilities.PushBack('Lvl99'); levelupAbilities.PushBack('Lvl100'); // Revert ciri locks if( inputHandler ) { inputHandler.BlockAllActions( 'being_ciri', false ); } SetBehaviorVariable( 'test_ciri_replacer', 0.0f); if(!spawnData.restored) { //toxicity` abilityManager.GainStat(BCS_Toxicity, 0); //to calculate current threshold } levelManager.PostInit(this, spawnData.restored); SetBIsCombatActionAllowed( true ); //PFTODO: should this get called when loading a game? SetBIsInputAllowed( true, 'OnSpawned' ); //PFTODO: should this get called when loading a game? //Reputation 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 ); //unlock skills for testing purposes //if(!theGame.IsFinalBuild() && !spawnData.restored ) // Debug_EquipTestingSkills(true); //cast sign currentlyCastSign = ST_None; //horse manager 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); } // HACK - removing Ciri abilities 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(); if(!newGamePlusInitialized && FactsQuerySum("NewGamePlus") > 0) { NewGamePlusInitialize(); } 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()); } } //failsafe - sometimes whirl does not end properly and keeps stamina lock, cannot pinpoint why this happens ResumeStaminaRegen('WhirlSkill'); if(HasAbility('Runeword 4 _Stats', true)) StartVitalityRegen(); isInitialized = true; //################ //AMM vAMM = new CAMM in this; AddTimer('InitAMM', 2.0, false); //AMM } //################# //AMM+ timer function InitAMM(dt : float, id : int) { vAMM.Init(); } //AMM- timer function DelayedHorseUpdate( dt : float, id : int ) { var man : W3HorseManager; man = GetHorseManager(); if(man) { if ( man.ApplyHorseUpdateOnSpawn() ) { RemoveTimer( 'DelayedHorseUpdate' ); } } } event OnAbilityAdded( abilityName : name) { super.OnAbilityAdded(abilityName); if(HasAbility('Runeword 4 _Stats', true)) StartVitalityRegen(); if ( GetStat(BCS_Focus, true) >= GetStatMax(BCS_Focus) && abilityName == 'Runeword 8 _Stats' && !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 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); } private final function ApplyPatchFixes() { var cnt, transmutationCount, mutagenCount, i : int; var transmutationAbility : name; var pam : W3PlayerAbilityManager; var slotId : int; var offset : float; var buffs : array<CBaseGameplayEffect>; var mutagen : 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"); } //fix for mutagen syngergy bonus (alchemy skill 19) not removed properly when under influence of Dimeritium Bomb 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"); } //tutorial for pinning recipes if(FactsQuerySum("DontShowRecipePinTut") < 1) { TutorialScript('alchemyRecipePin', ''); TutorialScript('craftingRecipePin', ''); } //potion reducing level requirement if(FactsQuerySum("LevelReqPotGiven") < 1) { FactsAdd("LevelReqPotGiven"); inv.AddAnItem('Wolf Hour', 1, false, false, true); } //missing auto stamina regen buff if(!HasBuff(EET_AutoStaminaRegen)) { AddEffectDefault(EET_AutoStaminaRegen, this, 'autobuff', false); } //wrongly implemented Transmutation skill AND //remaining offset toxicity after abilityManager object get corrupted and deleted buffs = GetBuffs(); offset = 0; mutagenCount = 0; for(i=0; i<buffs.Size(); i+=1) { mutagen = (W3Mutagen_Effect)buffs[i]; if(mutagen) { offset += mutagen.GetToxicityOffset(); mutagenCount += 1; } } //fix offset if(offset != (GetStat(BCS_Toxicity) - GetStat(BCS_Toxicity, true))) SetToxicityOffset(offset); //fix Transmutation 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); } //enchanting glossary tutorial if(theGame.GetDLCManager().IsEP1Available()) { theGame.GetJournalManager().ActivateEntryByScriptTag('TutorialJournalEnchanting', JS_Active); } } public final function RestoreQuen(quenHealth : float, quenDuration : float) : 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 ); restoredQuen.OnStarted(); restoredQuen.OnThrowing(); restoredQuen.OnEnded(); restoredQuen.SetDataFromRestore(quenHealth, quenDuration); return true; } return false; } public function IsInitialized() : bool { return isInitialized; } private final function NewGamePlusInitialize() { var questItems : array<name>; var horseManager : W3HorseManager; var horseInventory : CInventoryComponent; var i, missingLevels, expDiff : int; //get horse inventory - that's where the stash is horseManager = (W3HorseManager)EntityHandleGet(horseManagerHandle); if(horseManager) horseInventory = horseManager.GetInventoryComponent(); //set NG+ level to player level + few theGame.params.SetNewGamePlusLevel(GetLevel()); //increase player level if below 30 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<missingLevels; i+=1) { //M.J. Divide XP by 2 since AddPoints() will multiply it by 2 as we are in NG+ mode. expDiff = levelManager.GetTotalExpForNextLevel() - levelManager.GetPointsTotal(EExperiencePoint); expDiff = CeilF( ((float)expDiff) / 2 ); AddPoints(EExperiencePoint, expDiff, false); } //-- remove all quest items 1) and 2) //1) some non-quest items might dynamically have 'Quest' tag added so first we remove all items that //currently have Quest tag inv.RemoveItemByTag('Quest', -1); horseInventory.RemoveItemByTag('Quest', -1); //2) some quest items might lose 'Quest' tag during the course of the game so we need to check their //XML definitions rather than actual items in inventory questItems = theGame.GetDefinitionsManager().GetItemsWithTag('Quest'); for(i=0; i<questItems.Size(); i+=1) { inv.RemoveItemByName(questItems[i], -1); horseInventory.RemoveItemByName(questItems[i], -1); } //3) some quest items don't have 'Quest' tag at all inv.RemoveItemByName('mq1002_artifact_3', -1); horseInventory.RemoveItemByName('mq1002_artifact_3', -1); //4) some quest items are regular items but become quest items at some point - Quests will mark them with proper tag inv.RemoveItemByTag('NotTransferableToNGP', -1); horseInventory.RemoveItemByTag('NotTransferableToNGP', -1); //remove notice board notices - they are not quest items inv.RemoveItemByTag('NoticeBoardNote', -1); horseInventory.RemoveItemByTag('NoticeBoardNote', -1); //remove active buffs RemoveAllNonAutoBuffs(); //remove quest alchemy recipes RemoveAlchemyRecipe('Recipe for Trial Potion Kit'); RemoveAlchemyRecipe('Recipe for Pops Antidote'); RemoveAlchemyRecipe('Recipe for Czart Lure'); RemoveAlchemyRecipe('q603_diarrhea_potion_recipe'); //remove trophies inv.RemoveItemByTag('Trophy', -1); horseInventory.RemoveItemByTag('Trophy', -1); //remove usable items inv.RemoveItemByCategory('usable', -1); horseInventory.RemoveItemByCategory('usable', -1); //remove quest abilities RemoveAbility('StaminaTutorialProlog'); RemoveAbility('TutorialStaminaRegenHack'); RemoveAbility('area_novigrad'); RemoveAbility('NoRegenEffect'); RemoveAbility('HeavySwimmingStaminaDrain'); RemoveAbility('AirBoost'); RemoveAbility('area_nml'); RemoveAbility('area_skellige'); //remove Gwent cards inv.RemoveItemByTag('GwintCard', -1); horseInventory.RemoveItemByTag('GwintCard', -1); //remove readable items (maps, lore books etc - decision was to remove all) inv.RemoveItemByTag('ReadableItem', -1); horseInventory.RemoveItemByTag('ReadableItem', -1); //restore stats abilityManager.RestoreStats(); //unblock toxicity threshold ((W3PlayerAbilityManager)abilityManager).RemoveToxicityOffset(10000); //replenish alchemy items GetInventory().SingletonItemsRefillAmmo(); //remove crafting recipes craftingSchematics.Clear(); AddStartingSchematics(); //add clearing potion inv.AddAnItem('Clearing Potion', 1, true, false, false); //broken Ouroboros Mask inv.RemoveItemByName('q203_broken_eyeofloki', -1); horseInventory.RemoveItemByName('q203_broken_eyeofloki', -1); //replace NG+ Witcher items with "base" variants NewGamePlusReplaceViperSet(inv); NewGamePlusReplaceViperSet(horseInventory); NewGamePlusReplaceLynxSet(inv); NewGamePlusReplaceLynxSet(horseInventory); NewGamePlusReplaceGryphonSet(inv); NewGamePlusReplaceGryphonSet(horseInventory); NewGamePlusReplaceBearSet(inv); NewGamePlusReplaceBearSet(horseInventory); NewGamePlusReplaceEP1(inv); NewGamePlusReplaceEP1(horseInventory); //remove action locks from previous playthrough inputHandler.ClearLocksForNGP(); //remove buff immunities & removed immunities from previous playthrough buffImmunities.Clear(); buffRemovedImmunities.Clear(); newGamePlusInitialized = true; } private final function NewGamePlusReplaceItem( item : name, new_item : name, out inv : CInventoryComponent) { var i, j : int; var ids, new_ids, enh_ids : array<SItemUniqueId>; var enh : array<name>; var wasEquipped : bool; var wasEnchanted : bool; var enchantName : 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] ); 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]); } } } } private final function NewGamePlusAdjustDLCItem(item : name, mod : name, inv : CInventoryComponent) { var ids : array<SItemUniqueId>; 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); } 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); //reactionSystemOld 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; } //////////////////////////////////////////////////////////////////////////////// // // DEATH // //////////////////////////////////////////////////////////////////////////////// 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" ); } } } } } ////////////////////////////////////////////////////////////////////////////////////////// // // Input Section // ////////////////////////////////////////////////////////////////////////////////////////// function HandleMovement( deltaTime : float ) { super.HandleMovement( deltaTime ); rawCameraHeading = theCamera.GetCameraHeading(); } ////////////////////////////////////////////////////////////////////////////////////////// // // SETTERS & GETTERS // ////////////////////////////////////////////////////////////////////////////////////////// function ToggleSpecialAttackHeavyAllowed( toggle : bool) { specialAttackHeavyAllowed = toggle; } function GetReputationManager() : W3Reputation { return reputationManager; } function OnRadialMenuItemChoose( selectedItem : string ) //#B { var iSlotId : int; if ( selectedItem != "Slot3" ) { if ( rangedWeapon && rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) OnRangedForceHolster( true, false ); } switch(selectedItem) { /*case "Silver": if(IsItemEquippedByCategoryName('silversword')) { OnEquipMeleeWeapon( PW_Silver, false, true ); } break; case "Steel": if(IsItemEquippedByCategoryName('steelsword')) { OnEquipMeleeWeapon( PW_Steel, false, true ); } break; */ case "Meditation": theGame.RequestMenuWithBackground( 'MeditationClockMenu', 'CommonMenu' ); break; case "Slot1": SelectQuickslotItem(EES_Petard1); break; case "Slot2": SelectQuickslotItem(EES_Petard2); break; case "Slot3": SelectQuickslotItem(EES_RangedWeapon); break; case "Slot4": SelectQuickslotItem(EES_Quickslot1); break; case "Slot5": SelectQuickslotItem(EES_Quickslot2); 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 // just pick first valid { SelectQuickslotItem( quickSlotItems[ 0 ] ); } } // SIGNS 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; } // Called from code protected function IsInCombatActionCameraRotationEnabled() : bool { if( IsInCombatAction() && ( GetCombatAction() == EBAT_EMPTY || GetCombatAction() == EBAT_Parry ) ) { return true; } return !bIsInCombatAction; } function SetHoldBeforeOpenRadialMenuTime ( time : float ) { _HoldBeforeOpenRadialMenuTime = time; } ////////////////////////////////////////////////////////////////////////////////////////// // // @Repair Kits // ////////////////////////////////////////////////////////////////////////////////////////// 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 ( 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; } ////////////////////////////////////////////////////////////////////////////////////////// // // @Oils // ////////////////////////////////////////////////////////////////////////////////////////// //Returns oil item name (oil item can no longer exist in inventory) of oil applied to given sword (Steel if steel==true, Silver otherwise) public function GetOilAppliedOnSword(steel : bool) : name { var hasItem : bool; var sword : SItemUniqueId; if(steel) hasItem = GetItemEquippedOnSlot(EES_SteelSword, sword); else hasItem = GetItemEquippedOnSlot(EES_SilverSword, sword); if(!hasItem) return ''; //no sword return inv.GetSwordOil(sword); } // Returns true if given sword type is upgraded with given oil public function IsEquippedSwordUpgradedWithOil(steel : bool, optional oilName : name) : bool { var sword : SItemUniqueId; var i, minAbs, maxAbs : int; var hasItem : bool; var abilities, swordAbilities : array<name>; var dm : CDefinitionsManagerAccessor; var weights : array<float>; if(steel) hasItem = GetItemEquippedOnSlot(EES_SteelSword, sword); else hasItem = GetItemEquippedOnSlot(EES_SilverSword, sword); if(hasItem) { inv.GetItemAbilities(sword, swordAbilities); dm = theGame.GetDefinitionsManager(); if(IsNameValid(oilName)) { dm.GetItemAbilitiesWithWeights(oilName, true, abilities, weights, minAbs, maxAbs); for(i=0; i<abilities.Size(); i+=1) { if(dm.AbilityHasTag(abilities[i], theGame.params.OIL_ABILITY_TAG)) { if(swordAbilities.Contains(abilities[i])) { //there is an oil ability with oil tag that the sword has - that's enough return true; } } } } else { //checking for any oil for(i=0; i<swordAbilities.Size(); i+=1) { if(dm.AbilityHasTag(swordAbilities[i], theGame.params.OIL_ABILITY_TAG)) return true; } } } //if here then there is no oil ability from given oil on the sword return false; } //applies oil on given player item - adds oil bonus ability to item abilities public function ApplyOil( oilId : SItemUniqueId, usedOnItem : SItemUniqueId ) { var oilAbilities : array<name>; var i : int; var ammo, ammoBonus : float; var dm : CDefinitionsManagerAccessor; var swordEquipped : bool; var tutStateOil : W3TutorialManagerUIHandlerStateOils; var sword : CWitcherSword; if(!CanApplyOilOnItem(oilId, usedOnItem)) return; dm = theGame.GetDefinitionsManager(); inv.GetItemAbilitiesWithTag(oilId, theGame.params.OIL_ABILITY_TAG, oilAbilities); swordEquipped = IsItemEquipped(usedOnItem); //remove previous oil RemoveItemOil(usedOnItem); //add new oil for(i=0; i<oilAbilities.Size(); i+=1) { inv.AddItemCraftedAbility(usedOnItem, oilAbilities[i]); //When oil is equipped it adds its abilities to player. Since item is equipped it has already done that so we need to do it manually. if(swordEquipped) { AddAbility(oilAbilities[i]); } } if(swordEquipped) { sword = (CWitcherSword) inv.GetItemEntityUnsafe(usedOnItem); sword.ApplyOil( inv ); } //set charges //ammo = GetCurrentOilAmmo ( oilId ); ammo = CalculateAttributeValue(inv.GetItemAttributeValue(oilId, 'ammo')); if(CanUseSkill(S_Alchemy_s06)) { ammoBonus = CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s06, 'ammo_bonus', false, false)); ammo *= 1 + ammoBonus * GetSkillLevel(S_Alchemy_s06); } inv.SetItemModifierInt(usedOnItem, 'oil_charges', RoundMath(ammo)); inv.SetItemModifierInt(usedOnItem, 'oil_max_charges', RoundMath(ammo)); LogOils("Added oil <<" + inv.GetItemName(oilId) + ">> to <<" + inv.GetItemName(usedOnItem) + ">>"); //fundamentals first achievement SetFailedFundamentalsFirstAchievementCondition(true); //oils equip tutorial if(ShouldProcessTutorial('TutorialOilCanEquip3')) { tutStateOil = (W3TutorialManagerUIHandlerStateOils)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutStateOil) { tutStateOil.OnOilApplied(); } } theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnOilApplied ); } ////////////////////////////////////////////////////////////////////////////////////////// // // Damage // ////////////////////////////////////////////////////////////////////////////////////////// //FIXME this is foobar - sign tests should be moved to actor or entity. This will be usefull when npc will have signs or sign-like spells. function ReduceDamage(out damageData : W3DamageAction) { var actorAttacker : CActor; var quen : W3QuenEntity; var attackRange : CAIAttackRange; var attackerMovementAdjustor : CMovementAdjustor; var dist, distToAttacker, actionHeading, attackerHeading : float; var attackName : name; var useQuenForBleeding : bool; super.ReduceDamage(damageData); //HACK for bleeding and quen - since bleeding does direct damage it's not considered in super //but we want quen to reduce it 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; //damage prevented in super if(!useQuenForBleeding && !damageData.DealsAnyDamage()) return; actorAttacker = (CActor)damageData.attacker; //dodging if(actorAttacker && IsCurrentlyDodging() && damageData.CanBeDodged()) { //check if we're dodging straight on attacker or +/- 30 degrees off. If so then the damage will not be prevented //if( ( AbsF(AngleDistance(GetCombatActionHeading(), actorAttacker.GetHeading())) < 150 ) && ( !actorAttacker.GetIgnoreImmortalDodge() ) ) 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(); } // S_sword_s9 - decrease damage while dodging else if (!(damageData.IsActionEnvironment() || damageData.IsDoTDamage()) && CanUseSkill(S_Sword_s09)) { damageData.processedDmg.vitalityDamage *= 1 - ( CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s09, 'damage_reduction', false, true)) * GetSkillLevel(S_Sword_s09) ); if ( theGame.CanLog() ) { LogDMHits("W3PlayerWitcher.ReduceDamage: skill S_Sword_s09 reduced damage while dodging", damageData ); } } } //damage reduction from signs if(quen && damageData.GetBuffSourceName() != "FallingDamage") { if ( theGame.CanLog() ) { LogDMHits("W3PlayerWitcher.ReduceDamage: Processing Quen sign damage reduction...", damageData); } quen.OnTargetHit( damageData ); } } timer function UndyingSkillCooldown(dt : float, id : int) { cannotUseUndyingSkill = false; } event OnTakeDamage( action : W3DamageAction) { var currVitality, 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<SItemUniqueId>; var i : int; currVitality = GetStat(BCS_Vitality); //death preventing effects if(action.processedDmg.vitalityDamage >= currVitality) { //skill that prevents fatal damage & removes battle trance and focus points 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)); action.processedDmg.vitalityDamage = GetStatMax(BCS_Vitality) - healingFactor; DrainFocus(GetStat(BCS_Focus)); RemoveBuff(EET_BattleTrance); cannotUseUndyingSkill = true; AddTimer('UndyingSkillCooldown', CalculateAttributeValue( GetSkillAttributeValue(S_Sword_s18, 'trigger_delay', false, true) ), false, , , true); } else { //"Reinforced" special item ability. When fatal blows comes, item takes all damage on itself (durability) and prevents death. equipped = GetEquippedItems(); for(i=0; i<equipped.Size(); i+=1) { if ( !inv.IsIdValid( equipped[i] ) ) { continue; } itemDurability = inv.GetItemDurability(equipped[i]); if(inv.ItemHasAbility(equipped[i], 'MA_Reinforced') && itemDurability > 0) { //break item inv.SetItemDurabilityScript(equipped[i], MaxF(0, itemDurability - action.processedDmg.vitalityDamage) ); //prevent damage action.processedDmg.vitalityDamage = 0; ForceSetStat(BCS_Vitality, 1); break; } } } } //mutagen 10, 15 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() ); } //mutagen 19 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(); } } //mutagen 27 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); } } return super.OnTakeDamage(action); } ////////////////////////////////////////////////////////////////////////////////////////// // // @Combat // ////////////////////////////////////////////////////////////////////////////////////////// event OnStartFistfightMinigame() { super.OnStartFistfightMinigame(); effectManager.RemoveAllPotionEffects(); } event OnEndFistfightMinigame() { super.OnEndFistfightMinigame(); } //crit hit chance 0-1 public function GetCriticalHitChance(isHeavyAttack : bool, target : CActor, victimMonsterCategory : EMonsterCategory) : float { var ret : float; var thunder : W3Potion_Thunderbolt; ret = super.GetCriticalHitChance(isHeavyAttack, target, victimMonsterCategory); //Perk_05 bonus //if(!isHeavyAttack) //{ // ret += CalculateAttributeValue(GetAttributeValue('critical_hit_chance_fast_style')); //} thunder = (W3Potion_Thunderbolt)GetBuff(EET_Thunderbolt); if(thunder && thunder.GetBuffLevel() == 3 && GetCurWeather() == EWE_Storm) { ret += 1.0f; } return ret; } //gets damage bonus for critical hit public function GetCriticalHitDamageBonus(weaponId : SItemUniqueId, victimMonsterCategory : EMonsterCategory, isStrikeAtBack : bool) : SAbilityAttributeValue { var min, max, bonus, null, oilBonus : SAbilityAttributeValue; var mutagen : CBaseGameplayEffect; var vsAttributeName : name; bonus = super.GetCriticalHitDamageBonus(weaponId, victimMonsterCategory, isStrikeAtBack); //alchemy oil criticical damage skill bonus if(inv.ItemHasOilApplied(weaponId) && GetStat(BCS_Focus) >= 3 && CanUseSkill(S_Alchemy_s07)) { vsAttributeName = MonsterCategoryToCriticalDamageBonus(victimMonsterCategory); oilBonus = inv.GetItemAttributeValue(weaponId, vsAttributeName); if(oilBonus != null) //has proper oil type { bonus += GetSkillAttributeValue(S_Alchemy_s07, theGame.params.CRITICAL_HIT_DAMAGE_BONUS, false, true); } } // Mutagen 11 - back strike bonus 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; } ////////////////////////////////////////////////////////////////////////////////////////// // // @Combat Actions // ////////////////////////////////////////////////////////////////////////////////////////// /*script*/ event OnPocessActionPost(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<name>; var i : int; var dm : CDefinitionsManagerAccessor; var items : array<SItemUniqueId>; var weaponEnt : CEntity; super.OnPocessActionPost(action); attackAction = (W3Action_Attack)action; actorVictim = (CActor)action.victim; if(attackAction) { if(attackAction.IsActionMelee()) { //Rend aka special attack heavy if(SkillNameToEnum(attackAction.GetAttackTypeName()) == S_Sword_s02) { rendLoad = GetSpecialAttackTimeRatio(); //consumed focus is lesser of two: current focus and (rend time held * max focus) rendLoad = MinF(rendLoad * GetStatMax(BCS_Focus), GetStat(BCS_Focus)); //used points are treated as INTs rendLoad = FloorF(rendLoad); DrainFocus(rendLoad); OnSpecialAttackHeavyActionProcess(); } else if(actorVictim && IsRequiredAttitudeBetween(this, actorVictim, true)) { //focus gain on hit - rend gives none // M.J Each attack gives the same number of adrenaline value = GetAttributeValue('focus_gain'); if( FactsQuerySum("debug_fact_focus_boy") > 0 ) { Debug_FocusBoyFocusGain(); } //bonus from skill if ( CanUseSkill(S_Sword_s20) ) { value += GetSkillAttributeValue(S_Sword_s20, 'focus_gain', false, true) * GetSkillLevel(S_Sword_s20); } GainStat(BCS_Focus, 0.1f * (1 + CalculateAttributeValue(value)) ); } //tutorial - using wrong sword type. Display only when hitting hostiles (even if you can hit neutrals / friendlies) 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'); } } //runeword infusing sword with sign power 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; //stop fx 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'); } //light / heavy attacks tutorial 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()) { //bolt focus gain (if has skill) if(CanUseSkill(S_Sword_s15)) { value = GetSkillAttributeValue(S_Sword_s15, 'focus_gain', false, true) * GetSkillLevel(S_Sword_s15) ; GainStat(BCS_Focus, CalculateAttributeValue(value) ); } //skill: critical crossbow hit disables 1 random enemy skill if(CanUseSkill(S_Sword_s12) && attackAction.IsCriticalHit() && actorVictim) { //get non-blocked abilities of victim abs = actorVictim.GetAbilities(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 there is any non-blocked ability - pick random and block it 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)); } } } } //perk generating adrenaline on bomb non-DoT damage 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)); } } //mutagen 14 - attack power bonus 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 { //max stack reached 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; super.OnCombatStart(); if ( IsInCombatActionFriendly() ) { SetBIsCombatActionAllowed(true); SetBIsInputAllowed(true, 'OnCombatActionStart' ); } //mutagen 14 - attack power bonus if(HasBuff(EET_Mutagen14)) { AddTimer('Mutagen14Timer', 2, true); } //mutagen 15 - attack power bonus if(HasBuff(EET_Mutagen15)) { AddAbility(GetBuff(EET_Mutagen15).GetAbilityName(), false); } //check if quen is currently on quenEntity = (W3QuenEntity)signs[ST_Quen].entity; //if has some quen 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); } //abort meditation MeditationForceAbort(true); } //called when combat finishes event OnCombatFinished() { var mut17 : W3Mutagen17_Effect; super.OnCombatFinished(); //mutagen 10 disable if(HasBuff(EET_Mutagen10)) { RemoveAbilityAll( GetBuff(EET_Mutagen10).GetAbilityName() ); } //mutagen 14 disable if(HasBuff(EET_Mutagen14)) { RemoveAbilityAll( GetBuff(EET_Mutagen14).GetAbilityName() ); } //mutagen 15 disable if(HasBuff(EET_Mutagen15)) { RemoveAbilityAll( GetBuff(EET_Mutagen15).GetAbilityName() ); } //mutagen 17 disable if(HasBuff(EET_Mutagen17)) { mut17 = (W3Mutagen17_Effect)GetBuff(EET_Mutagen17); mut17.ClearBoost(); } //mutagen 18 disable if(HasBuff(EET_Mutagen18)) { RemoveAbilityAll( GetBuff(EET_Mutagen18).GetAbilityName() ); } //mutagen 22 disable if(HasBuff(EET_Mutagen22)) { RemoveAbilityAll( GetBuff(EET_Mutagen22).GetAbilityName() ); } //mutagen 27 disable if(HasBuff(EET_Mutagen27)) { RemoveAbilityAll( GetBuff(EET_Mutagen27).GetAbilityName() ); } //adrenaline drain if(GetStat(BCS_Focus) > 0) { AddTimer('DelayedAdrenalineDrain', theGame.params.ADRENALINE_DRAIN_AFTER_COMBAT_DELAY, , , , true); } //Removing overheal bonus thePlayer.abilityManager.ResetOverhealBonus(); usedQuenInCombat = false; theGame.GetGamerProfile().ResetStat(ES_FinesseKills); //---=== modFriendlyHUD ===--- if( !GetFHUDConfig().dontTouchMySwords ) { //modNoAutoSwordSheath /* LogChannel( 'OnCombatFinished', "OnCombatFinished: DelayedSheathSword timer added" ); if ( ShouldAutoSheathSwordInstantly() ) AddTimer( 'DelayedSheathSword', 0.5f ); else AddTimer( 'DelayedSheathSword', 2.f ); */ //---=== modFriendlyHUD ===--- OnBlockAllCombatTickets( false ); // failsafe for killing opponents with debug keys //'discharge' Runeword 1 infusion runewordInfusionType = ST_None; /*if ( !this.IsThreatened() ) { if ( this.IsInCombatAction() ) this.PushCombatActionOnBuffer(EBAT_Sheathe_Sword,BS_Pressed); else OnEquipMeleeWeapon( PW_None, false ); }*/ } timer function DelayedAdrenalineDrain(dt : float, id : int) { if ( !HasBuff(EET_Runeword8) ) AddEffectDefault(EET_AdrenalineDrain, this, "after_combat_adrenaline_drain"); } //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<CActor>, 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; //drain stamina DrainStamina(ESAT_Ability, 0, 0, GetSkillAbilityName(S_Sword_s02), dt); //abort if out of stamina if(GetStat(BCS_Stamina) <= 0) OnPerformSpecialAttack(false, false); //update 'held' ratio ratio = EngineTimeToFloat(theGame.GetEngineTime() - specialHeavyStartEngineTime) / specialHeavyChargeDuration; //rounding and blend-out errors if(ratio > 0.95) ratio = 1; SetSpecialAttackTimeRatio(ratio); //calculate focus point cost and highlight 'to be used' focus points on HUD 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)) ) { //tutorial - even if input is not allowed - we might get caught with slowmo during previous dodge - so dodge is not allowed then 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() ) ) { //bIsRollAllowed = true; 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); } } //All input mechanics are in here 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; //call super if(super.ProcessCombatActionBuffer()) return true; //... and quit if processed switch ( action ) { case EBAT_CastSign : { switch ( stage ) { case BS_Pressed : { // if ( GetInvalidUniqueId() == inv.GetItemFromSlot( 'l_weapon' ) ) // { // if ( ( !rangedWeapon || !( rangedWeapon.PerformedDraw() || rangedWeapon.GetCurrentStateName() != 'State_WeaponWait' ) ) // && !currentlyUsingItem ) // if ( !currentlyUsingItem ) // { actionResult = this.CastSign(); LogChannel('SignDebug', "CastSign()"); // } // } } break; default : { actionResult = false; } break; } } break; case EBAT_SpecialAttack_Light : { switch ( stage ) { case BS_Pressed : { //AddTemporarySkills(); 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 : { //AddTemporarySkills(); actionResult = this.OnPerformSpecialAttack( false, true ); } break; case BS_Released : { actionResult = this.OnPerformSpecialAttack( false, false ); } break; default : { actionResult = false; } break; } } break; default: return false; //not processed } //if here then buffer got processed this.CleanCombatActionBuffer(); if (actionResult) { SetCombatAction( action ) ; } return true; } /* 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 OnPerformSpecialAttack( isLightAttack : bool, enableAttack : bool ){} event OnPlayerTickTimer( deltaTime : float ) { super.OnPlayerTickTimer( deltaTime ); if ( !IsInCombat() ) { fastAttackCounter = 0; heavyAttackCounter = 0; } } ////////////////// // @attacks ////////////////// protected function PrepareAttackAction( hitTarget : CGameplayEntity, animData : CPreAttackEventData, weaponId : SItemUniqueId, parried : bool, countered : bool, parriedBy : array<CActor>, 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; //Skill bonuses 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<CActor> { //rend cannot be parried 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; } //---------------------------------------------- @CRAFTING -------------------------------------------------------- public function GetCraftingSchematicsNames() : array<name> {return craftingSchematics;} public function RemoveAllCraftingSchematics() { craftingSchematics.Clear(); } /** Adds new schematic to the book. Returns true if the schematic was added, false if it's already in the book. */ 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<craftingSchematics.Size(); i+=1) { if(craftingSchematics[i] == nam) return false; //found a place to insert if(StrCmp(craftingSchematics[i],nam) > 0) { craftingSchematics.Insert(i,nam); AddCraftingHudNotification( nam, isSilent ); theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_CraftingSchematics ); return true; } } //if here then either the array is empty or 'nam' should be inserted at the end 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 ); } } } //////////////////////////////////////////////////////////////////////////////// // // @Alchemy // //////////////////////////////////////////////////////////////////////////////// public function GetAlchemyRecipes() : array<name> { 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; /* unused perk 8 if(dm.GetCustomNodeAttributeValueInt( recipeNode, 'level', tmpInt)) { if(tmpInt >= 3) { return CanUseSkill(S_Perk_08); } else { return true; } } else { return true; } */ } return false; } private final function RemoveAlchemyRecipe(recipeName : name) { alchemyRecipes.Remove(recipeName); } private final function RemoveAllAlchemyRecipes() { alchemyRecipes.Clear(); } /** Adds new recipe to the book. Returns true if the recipe was added, false if it's already in the book. */ 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<string>; var strRecipeName, recipeNameWithoutLevel : string; if(!IsAlchemyRecipe(nam)) return false; found = false; for(i=0; i<alchemyRecipes.Size(); i+=1) { if(alchemyRecipes[i] == nam) return false; //found a place to insert 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); //skill toxicity increase 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); } //achievement for learning - need to do a full pass due to desync between RC and patch versions potions = 0; bombs = 0; for(i=0; i<alchemyRecipes.Size(); i+=1) { m_alchemyManager.GetRecipe(alchemyRecipes[i], recipe); //potions are not unique if(recipe.cookedItemType == EACIT_Potion || recipe.cookedItemType == EACIT_MutagenPotion || recipe.cookedItemType == EACIT_Alcohol || recipe.cookedItemType == EACIT_Quest) { potions += 1; } //bombs are unique else 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_KnownPotionRecipes, potions); theGame.GetGamerProfile().SetStat(ES_KnownBombRecipes, bombs); theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_AlchemyRecipe ); return true; } ////////////////////////////////////////////////////////////////////////////////////////// // // Combat Actions GUI Mediator //#B // ////////////////////////////////////////////////////////////////////////////////////////// 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; } ////////////////////////////////////////////////////////////////////////////////////////// // // Witcher's Throw Item Mechanics // ////////////////////////////////////////////////////////////////////////////////////////// public function SelectQuickslotItem( slot : EEquipmentSlots ) { var item : SItemUniqueId; GetItemEquippedOnSlot(slot, item); selectedItemId = item; //invalid if no item } ///////////////////////////////////////////////////////////////////////////////// // // MEDALLION // ///////////////////////////////////////////////////////////////////////////////// public function GetMedallion() : W3MedallionController { if ( !medallionController ) { medallionController = new W3MedallionController in this; } return medallionController; } // Medallion highlighted objects public final function HighlightObjects(range : float, optional highlightTime : float ) { var ents : array<CGameplayEntity>; var i : int; FindGameplayEntitiesInSphere(ents, GetWorldPosition(), range, 100, 'HighlightedByMedalionFX', FLAG_ExcludePlayer); if(highlightTime == 0) highlightTime = 30; for(i=0; i<ents.Size(); i+=1) { if(!ents[i].IsHighlighted()) { ents[i].SetHighlighted( true ); ents[i].PlayEffectSingle( 'medalion_detection_fx' ); ents[i].AddTimer( 'MedallionEffectOff', highlightTime ); } } } // highlighted enemies public final function HighlightEnemies(range : float, optional highlightTime : float ) { var ents : array<CGameplayEntity>; var i : int; var catComponent : CGameplayEffectsComponent; FindGameplayEntitiesInSphere(ents, GetWorldPosition(), range, 100, , FLAG_ExcludePlayer + FLAG_OnlyAliveActors); if(highlightTime == 0) highlightTime = 5; for(i=0; i<ents.Size(); i+=1) { if(IsRequiredAttitudeBetween(this, ents[i], true)) { catComponent = GetGameplayEffectsComponent(ents[i]); if(catComponent) { catComponent.SetGameplayEffectFlag(EGEF_CatViewHiglight, true); ents[i].AddTimer( 'EnemyHighlightOff', highlightTime ); } } } } function SpawnMedallionEntity() { var rot : EulerAngles; var spawnedMedallion : CEntity; spawnedMedallion = theGame.GetEntityByTag( 'new_Witcher_medallion_FX' ); if ( !spawnedMedallion ) theGame.CreateEntity( medallionEntity, GetWorldPosition(), rot, true, false ); } ///////////////////////////////////////////////////////////////////////////////// // // COMBAT FOCUS // ///////////////////////////////////////////////////////////////////////////////// // Yes! Empty space! public final function InterruptCombatFocusMode() { if( this.GetCurrentStateName() == 'CombatFocusMode_SelectSpot' ) { SetCanPlayHitAnim( true ); PopState(); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////// @EQUIPMENT @SLOTS @ITEMS //////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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; } //Flips selected potion between two slots (upper or lower). Returns true if flip actually occured. 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('BombDelay1', 0.1, true); } else if(slot == EES_Petard2 || slot == EES_Quickslot2) { remainingBombThrowDelaySlot2 = theGame.params.BOMB_THROW_DELAY; AddTimer('BombDelay2', 0.1, true); } } 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 BombDelay1(dt : float, id : int) { remainingBombThrowDelaySlot1 -= dt; if(remainingBombThrowDelaySlot1 <= 0) RemoveTimer('BombDelay1'); } timer function BombDelay2(dt : float, id : int) { remainingBombThrowDelaySlot2 -= dt; if(remainingBombThrowDelaySlot2 <= 0) RemoveTimer('BombDelay2'); } public function ResetCharacterDev() { //char dev mutagens UnequipItemFromSlot(EES_SkillMutagen1); UnequipItemFromSlot(EES_SkillMutagen2); UnequipItemFromSlot(EES_SkillMutagen3); UnequipItemFromSlot(EES_SkillMutagen4); levelManager.ResetCharacterDev(); ((W3PlayerAbilityManager)abilityManager).ResetCharacterDev(); } public function ConsumeItem( itemId : SItemUniqueId ) : bool { var itemName : name; var removedItem, willRemoveItem : bool; var edibles : array<SItemUniqueId>; var toSlot : EEquipmentSlots; var i : int; var equippedNewEdible : bool; itemName = inv.GetItemName( itemId ); if (itemName == 'q111_imlerith_acorn' ) // MEGA HACK STARTS { AddPoints(ESkillPoint, 2, true); removedItem = inv.RemoveItem( itemId, 1 ); theGame.GetGuiManager().ShowNotification( GetLocStringByKeyExt("panel_character_popup_title_buy_skill") + "<br>" + GetLocStringByKeyExt("panel_character_availablepoints") + " +2"); theSound.SoundEvent("gui_character_buy_skill"); // #J Not sure if best sound, but its better than no sound } 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"); // #J Not sure if best sound, but its better than no sound } else if(itemName == 'Wolf Hour') { removedItem = inv.RemoveItem( itemId, 1 ); theSound.SoundEvent("gui_character_synergy_effect"); // #J Not sure if best sound, but its better than no sound AddEffectDefault(EET_WolfHour, thePlayer, 'wolf hour'); } 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; //look for non-alcohol for(i=0; i<edibles.Size(); i+=1) { 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; } } //take alco if only has alco if(!equippedNewEdible) { for(i=0; i<edibles.Size(); i+=1) { 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; } //returns item ID (or empty if none) of item that can be used to refill alchemical items in meditation public final function GetAlcoholForAlchemicalItemsRefill() : SItemUniqueId { var alcos : array<SItemUniqueId>; 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<alcos.Size(); i+=1) { 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(); } //adds and equips infinite bolts of proper type public final function AddAndEquipInfiniteBolt(optional forceBodkin : bool, optional forceHarpoon : bool) { var bolt, bodkins, harpoons : array<SItemUniqueId>; var boltItemName : name; var i : int; //failsafe - remove any infinite bolts if they're in inventory for some reason 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]) ); //Check which bolt is needed. //Note: all three checks for swimming are NOT guaranteed to work, hence optional force flags if(!forceBodkin && (forceHarpoon || GetCurrentStateName() == 'Swimming' || IsSwimming() || IsDiving()) ) { boltItemName = 'Harpoon Bolt'; } else { boltItemName = 'Bodkin Bolt'; } //select previous special ammo if(boltItemName == 'Bodkin Bolt' && inv.IsIdValid(previouslyUsedBolt)) { bolt.PushBack(previouslyUsedBolt); } else { //add bolt bolt = inv.AddAnItem(boltItemName, 1, true, true); //if harpoon then we store previously used special bolt if any to restore once we leave water if(boltItemName == 'Harpoon Bolt') { GetItemEquippedOnSlot(EES_Bolt, previouslyUsedBolt); } } EquipItem(bolt[0], EES_Bolt); } //called when item is added to players inventory through ANY means event OnItemGiven(data : SItemChangedData) { var m_guiManager : CR4GuiManager; super.OnItemGiven(data); //player object may not exist at this point. As much as impossible that sounds - it does happen (as a result inv is not set) if(!inv) inv = GetInventory(); //update encumbrance if(inv.IsItemEncumbranceItem(data.ids[0])) UpdateEncumbrance(); m_guiManager = theGame.GetGuiManager(); if(m_guiManager) m_guiManager.RegisterNewItem(data.ids[0]); } //checks progress towards FullyArmed achievement and gives it if applicable 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) ) { theGame.GetGamerProfile().AddAchievement(EA_FullyArmed); } } //checks if player has all items from witcher set with given tag equipped 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; //hack for some sets having also a crossbow 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; } /* few nice checks are in here so I leave it for the time being private function CanPlaceMobileCampfire(out position : Vector) : bool { var colPos, normal, headPosition : Vector; var world : CWorld; var test : float; position = Vector(0, 0, 0); //check if is allowed to place it at all if(GetCurrentStateName() != 'Exploration' || isOnBoat || IsInInterior() || IsInSettlement()) return false; //ground test position = GetWorldPosition() + VecNormalize(GetHeadingVector()) * 0.5; world = theGame.GetWorld(); if(!world.StaticTrace(position + Vector(0,0,1), position - Vector(0,0,0.5), colPos, normal)) return false; //void cannot place position = colPos; //snapped to ground position //underwater test = world.GetWaterLevel(position, true); if(position.Z <= world.GetWaterLevel(position, true)) return false; //not navigable area - cannot reach so most likely no place if(!world.NavigationCircleTest(position, 0.4)) return false; //actor occupies that spot - cannot place if(!theGame.TestNoCreaturesOnLocation(position, 0.4, this)) return false; //behind wall - line of sight check headPosition = GetBoneWorldPosition('head'); if(world.StaticTrace(headPosition, position, colPos, normal ) ) { //small deviation is fine if(VecDistance(colPos, position) > 0.1) return false; } return true; } */ //returns total armor public function GetTotalArmor() : SAbilityAttributeValue { var armor : SAbilityAttributeValue; var armorItem : SItemUniqueId; armor = super.GetTotalArmor(); if(GetItemEquippedOnSlot(EES_Armor, armorItem)) { //subtract base item armor armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); //add real armor armor += inv.GetItemArmorTotal(armorItem); } if(GetItemEquippedOnSlot(EES_Pants, armorItem)) { //subtract base item armor armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); //add real armor armor += inv.GetItemArmorTotal(armorItem); } if(GetItemEquippedOnSlot(EES_Boots, armorItem)) { //subtract base item armor armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); //add real armor armor += inv.GetItemArmorTotal(armorItem); } if(GetItemEquippedOnSlot(EES_Gloves, armorItem)) { //subtract base item armor armor -= inv.GetItemAttributeValue(armorItem, theGame.params.ARMOR_VALUE_NAME); //add real armor armor += inv.GetItemArmorTotal(armorItem); } return armor; } //Picks random armor item and reduces its durability. //Returns slot of the item that got reduced or EES_InvalidSlot if nothing reduced public function ReduceArmorDurability() : EEquipmentSlots { var r, sum : int; var slot : EEquipmentSlots; var id : SItemUniqueId; var prevDurMult, currDurMult, ratio : float; //pick item slot 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; //theGame.params.DURABILITY_ARMOR_MISS_WEIGHT GetItemEquippedOnSlot(slot, id); ratio = inv.GetItemDurabilityRatio(id); //ratio before reduction if(inv.ReduceItemDurability(id)) //auto-handles invalid id and no defined durability { prevDurMult = theGame.params.GetDurabilityMultiplier(ratio, false); ratio = inv.GetItemDurabilityRatio(id); currDurMult = theGame.params.GetDurabilityMultiplier(ratio, false); if(currDurMult != prevDurMult) { //if durability threshold changed then recalc resists //currently affects only armor //((W3PlayerAbilityManager)abilityManager).RecalcItemResistDurability(slot, id); } return slot; } return EES_InvalidSlot; } //returns true if item was dismantled public function DismantleItem(dismantledItem : SItemUniqueId, toolItem : SItemUniqueId) : bool { var parts : array<SItemParts>; var i : int; if(!inv.IsItemDismantleKit(toolItem)) return false; parts = inv.GetItemRecyclingParts(dismantledItem); if(parts.Size() <= 0) return false; for(i=0; i<parts.Size(); i+=1) inv.AddAnItem(parts[i].itemName, parts[i].quantity, true, false); inv.RemoveItem(toolItem); inv.RemoveItem(dismantledItem); return true; } //gets item from given slot to out param *item*, returns true if the ID is valid 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); } //returns slot on which this item is equipped or invalid if this item is not equipped or player does not have it public function GetItemSlotByItemName(itemName : name) : EEquipmentSlots { var ids : array<SItemUniqueId>; var i : int; var slot : EEquipmentSlots; ids = inv.GetItemsByName(itemName); for(i=0; i<ids.Size(); i+=1) { slot = GetItemSlot(ids[i]); if(slot != EES_InvalidSlot) return slot; } return EES_InvalidSlot; } //returns slot on which this item is equipped or invalid if this item is not equipped or item id is invalid public function GetItemSlot(item : SItemUniqueId) : EEquipmentSlots { var i : int; if(!inv.IsIdValid(item)) return EES_InvalidSlot; for(i=0; i<itemSlots.Size(); i+=1) if(itemSlots[i] == item) return i; return EES_InvalidSlot; } public function GetEquippedItems() : array<SItemUniqueId> { return itemSlots; } public function IsItemEquipped(item : SItemUniqueId) : bool { if(!inv.IsIdValid(item)) return false; return itemSlots.Contains(item); } //returns true if any item is equipped on given slot public function IsAnyItemEquippedOnSlot(slot : EEquipmentSlots) : bool { if(slot == EES_InvalidSlot || slot < 0 || slot > EnumGetMax('EEquipmentSlots')) return false; return inv.IsIdValid(itemSlots[slot]); } //returns next free quickslot or EES_InvalidSlot if all are occupied public function GetFreeQuickslot() : EEquipmentSlots { if(!inv.IsIdValid(itemSlots[EES_Quickslot1])) return EES_Quickslot1; if(!inv.IsIdValid(itemSlots[EES_Quickslot2])) return EES_Quickslot2; /*if(!inv.IsIdValid(itemSlots[EES_Quickslot3])) return EES_Quickslot3; if(!inv.IsIdValid(itemSlots[EES_Quickslot4])) return EES_Quickslot4; if(!inv.IsIdValid(itemSlots[EES_Quickslot5])) return EES_Quickslot5;*/ return EES_InvalidSlot; } // Used by things like cut scenes which may mount things independently event OnEquipItemRequested(item : SItemUniqueId, ignoreMount : bool) { var slot : EEquipmentSlots; if(inv.IsIdValid(item)) { slot = inv.GetSlotForItemId(item); if (slot != EES_InvalidSlot) { //#J [WARNING] might want to eventually add a parameter for toHand, currently ignoreMount is always false so it doesn't matter //(trying to fix P0 quickly so covering hypothetical uses that may never come to be seems like waste of time) EquipItemInGivenSlot(item, slot, ignoreMount); } } } event OnUnequipItemRequested(item : SItemUniqueId) { UnequipItem(item); } /* Equips given item. If you don't provide the slot it will find appropriate one and equip there. If it's a multiple slot group (e.g. quickslots or potion slots) it will try to find next free slot. If it cannot then the default slot will be used. If toHand is set then given item will be made *held*, that is it's entity will be put in witcher hands. Returns true if item was successfully equipped. */ 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; } return EquipItemInGivenSlot(item, slot, false, toHand); } protected function ShouldMount(slot : EEquipmentSlots, item : SItemUniqueId, category : name):bool { //AK: don't mount potion mutagens in inventory //PB: don't mount usable items (will be mounted on use) 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<SItemUniqueId>; 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 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 function EquipItemInGivenSlot(item : SItemUniqueId, slot : EEquipmentSlots, ignoreMounting : bool, optional toHand : bool) : bool { var i, groupID : int; var fistsID : array<SItemUniqueId>; var pam : W3PlayerAbilityManager; var isSkillMutagen : bool; var armorEntity : CItemEntity; var armorMeshComponent : CComponent; var armorSoundIdentification : name; var category : name; var prevSkillColor : ESkillColor; var containedAbilities : array<name>; var dm : CDefinitionsManagerAccessor; var armorType : EArmorType; var otherMask, previousItemInSlot : SItemUniqueId; var tutStatePot : W3TutorialManagerUIHandlerStatePotions; var tutStateFood : W3TutorialManagerUIHandlerStateFood; var tutStateSecondPotionEquip : W3TutorialManagerUIHandlerStateSecondPotionEquip; var boltItem : SItemUniqueId; 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)) { //player does not meet level requirement return false; } if(inv.ItemHasTag(item, 'PhantomWeapon') && !GetPhantomWeaponMgr()) { InitPhantomWeaponMgr(); } //swapping items - just reassign in slots, don't do any logic previousItemInSlot = itemSlots[slot]; if(/*inv.IsIdValid(previousItemInSlot) &&*/ IsItemEquipped(item)) // #Y potions and bombs can be swapped with empty item { SwapEquippedItems(slot, GetItemSlot(item)); return true; } //skill mutagens isSkillMutagen = IsSlotSkillMutagen(slot); if(isSkillMutagen) { pam = (W3PlayerAbilityManager)abilityManager; if(!pam.IsSkillMutagenSlotUnlocked(slot)) { return false; } } //unequip previous item if slot is occupied if(inv.IsIdValid(previousItemInSlot)) { if(!UnequipItemFromSlot(slot, true)) { LogAssert(false, "W3PlayerWitcher.EquipItem: Cannot equip item <<" + inv.GetItemName(item) + ">> !!"); return false; } } //if it's a mask unequip other equipped mask 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 ); //potion mutagens if( !ignoreMounting && ShouldMount(slot, item, category) ) { // force mounting mutagen skills (so that other mutagen skills won't be unmounted) 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); } } //default ammo 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" )); } } } //skill mutagen 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); } //fist fight bonus ability if(inv.ItemHasAbility(item, 'MA_HtH')) { inv.GetItemContainedAbilities(item, containedAbilities); fistsID = inv.GetItemsByName('fists'); dm = theGame.GetDefinitionsManager(); for(i=0; i<containedAbilities.Size(); i+=1) { if(dm.AbilityHasTag(containedAbilities[i], 'MA_HtH')) { inv.AddItemCraftedAbility(fistsID[0], containedAbilities[i], true); } } } //perk armor bonuses if(inv.IsItemAnyArmor(item)) { armorType = inv.GetArmorType(item); pam = (W3PlayerAbilityManager)abilityManager; if(armorType == EAT_Light) { if(CanUseSkill(S_Perk_05)) pam.UpdatePerkArmorBonus(S_Perk_05, true); } else if(armorType == EAT_Medium) { if(CanUseSkill(S_Perk_06)) pam.UpdatePerkArmorBonus(S_Perk_06, true); } else if(armorType == EAT_Heavy) { if(CanUseSkill(S_Perk_07)) pam.UpdatePerkArmorBonus(S_Perk_07, true); } } // report global event theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnItemEquipped ); //potion equip tutorial 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)); } } } //food equip tutorial if(ShouldProcessTutorial('TutorialFoodSelectTab')) { if( IsSlotPotionSlot(slot) && inv.IsItemFood(item)) { tutStateFood = (W3TutorialManagerUIHandlerStateFood)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutStateFood) { tutStateFood.OnFoodEquipped(); } } } //achievement for any fully equipped witcher set if(inv.IsItemSetItem(item)) { CheckForFullyArmedAchievement(); } return true; } private function CheckHairItem() { var ids : array<SItemUniqueId>; var i : int; var itemName : name; var hairApplied : bool; ids = inv.GetItemsByCategory('hair'); for(i=0; i<ids.Size(); i+= 1) { 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 ); } } //Tries to set crossbow object untill it succeeds timer function DelayedOnItemMount( dt : float, id : int ) { var crossbowID : SItemUniqueId; var invent : CInventoryComponent; invent = GetInventory(); if(!invent) return; //inventory component not streamed yet //get crossbow ID GetItemEquippedOnSlot(EES_RangedWeapon, crossbowID); if(invent.IsIdValid(crossbowID)) { //if has crossbow, get object rangedWeapon = ( Crossbow )(invent.GetItemEntityUnsafe(crossbowID) ); if(rangedWeapon) { //if succeeded finish, else will loop again RemoveTimer('DelayedOnItemMount'); } } else { //if no crossbow then nothing to set - abort RemoveTimer('DelayedOnItemMount'); } } public function GetHeldItems() : array<SItemUniqueId> { var items : array<SItemUniqueId>; 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; } /* Unequips item from given slot. Returns true if item was successfully removed. */ public function UnequipItemFromSlot(slot : EEquipmentSlots, optional reequipped : bool) : bool { var item, bolts : SItemUniqueId; var items : array<SItemUniqueId>; var retBool : bool; var fistsID, bolt : array<SItemUniqueId>; var i, groupID : int; var pam : W3PlayerAbilityManager; var prevSkillColor : ESkillColor; var containedAbilities : array<name>; 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; //remove mutagen potion effect if(IsSlotSkillMutagen(slot)) { //get current color bonus pam = (W3PlayerAbilityManager)abilityManager; groupID = pam.GetSkillGroupIdOfMutagenSlot(slot); prevSkillColor = pam.GetSkillGroupColor(groupID); } item = itemSlots[slot]; itemSlots[slot] = GetInvalidUniqueId(); // unequiping swords if(inv.ItemHasTag( item, 'PhantomWeapon' ) && GetPhantomWeaponMgr()) { DestroyPhantomWeaponMgr(); } //manage crosssbow and bolts under water //unequipping crossbow if(slot == EES_RangedWeapon) { this.OnRangedForceHolster( true, true ); rangedWeapon.ClearDeployedEntity(true); rangedWeapon = NULL; //if has equipped some infinite bolts, remove them 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(""); } //usable items if(currentlyEquipedItem == item) { currentlyEquipedItem = GetInvalidUniqueId(); RaiseEvent('ForcedUsableItemUnequip'); } if(currentlyEquipedItemL == item) { if ( currentlyUsedItemL ) { currentlyUsedItemL.OnHidden( this ); } HideUsableItem ( true ); } //unmount if mountable item if( !IsSlotPotionMutagen(slot) ) { GetInventory().UnmountItem(item, true); } retBool = true; //unequipping bolts if(IsAnyItemEquippedOnSlot(EES_RangedWeapon) && slot == EES_Bolt) { if(inv.ItemHasTag(item, theGame.params.TAG_INFINITE_AMMO)) { //unequipping infinite ammo bolts inv.RemoveItem(item, inv.GetItemQuantityByName( inv.GetItemName(item) ) ); } else if (!reequipped) { //unequipping finite ammo bolts AddAndEquipInfiniteBolt(); } } //if weapon was held in hand then update the character pose / combat state if(slot == EES_SilverSword || slot == EES_SteelSword) { OnEquipMeleeWeapon(PW_None, true); } if( /*IsSlotQuickslot(slot) || */ GetSelectedItemId() == item ) { ClearSelectedItemId(); } if(inv.IsItemBody(item)) { retBool = true; } if(retBool && !reequipped) { theTelemetry.LogWithLabelAndValue( TE_INV_ITEM_UNEQUIPPED, inv.GetItemName(item), slot ); //remove enhanced item buffs 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); } } //fist fight bonus ability if(inv.ItemHasAbility(item, 'MA_HtH')) { inv.GetItemContainedAbilities(item, containedAbilities); fistsID = inv.GetItemsByName('fists'); dm = theGame.GetDefinitionsManager(); for(i=0; i<containedAbilities.Size(); i+=1) { if(dm.AbilityHasTag(containedAbilities[i], 'MA_HtH')) { inv.RemoveItemCraftedAbility(fistsID[0], containedAbilities[i]); } } } //perk armor bonuses if(inv.IsItemAnyArmor(item)) { armorType = inv.GetArmorType(item); pam = (W3PlayerAbilityManager)abilityManager; if(armorType == EAT_Light || GetCharacterStats().HasAbility('Glyphword 2 _Stats', true)) { if(CanUseSkill(S_Perk_05)) pam.UpdatePerkArmorBonus(S_Perk_05, false); } if(armorType == EAT_Medium || GetCharacterStats().HasAbility('Glyphword 3 _Stats', true)) { if(CanUseSkill(S_Perk_06)) pam.UpdatePerkArmorBonus(S_Perk_06, false); } if(armorType == EAT_Heavy || GetCharacterStats().HasAbility('Glyphword 4 _Stats', true)) { if(CanUseSkill(S_Perk_07)) pam.UpdatePerkArmorBonus(S_Perk_07, false); } } if( slot == EES_Gloves ) { thePlayer.DestroyEffect('runeword_4'); } // Update broken item indicator hud = (CR4ScriptedHud)theGame.GetHud(); damagedItemModule = hud.GetDamagedItemModule(); damagedItemModule.OnItemUnequippedFromSlot( slot ); // report global event 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; } //Returns true if there is at least one item with given name or category equipped (others with same name might be unequipped) public function IsItemEquippedByName(itemName : name) : bool { var i : int; for(i=0; i<itemSlots.Size(); i+=1) if(inv.GetItemName(itemSlots[i]) == itemName) return true; return false; } //Returns true if there is at least one item of given category equipped (others with same name might be unequipped) public function IsItemEquippedByCategoryName(categoryName : name) : bool { var i : int; for(i=0; i<itemSlots.Size(); i+=1) 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<SItemUniqueId>; var inve : CInventoryComponent; inve = GetInventory(); //called before geralt is spawned -> inv == NULL inve.GetAllItems(items); for(i=0; i<items.Size(); i+=1) { if( inv.IsItemEncumbranceItem( items[i] ) ) { encumbrance += inve.GetItemEncumbrance( items[i] ); //LogPotions("Item: " + inve.GetItemName( items[i] ) + " with Weight: " + inve.GetItemWeight( items[i] ) + " adds Encumberance: " + inve.GetItemEncumbrance(items[i]) + "."); } } return encumbrance; } //optimize me! public function UpdateEncumbrance() { var temp : bool; //we add bonus 1 point because UI shows this as int rather than float, so having 150.9 / 150 is shown as 150/150 //so from player's perspective you should not be overburdened if ( GetEncumbrance() >= (GetMaxRunEncumbrance(temp) + 1) ) { if( !HasBuff(EET_OverEncumbered) ) { 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; } ////////////////////////////////////////////////////////////////////////////////////////// // // Witcher's Signs // ////////////////////////////////////////////////////////////////////////////////////////// //returns next (left or right) sign type in cycle function CycleSelectSign( bIsCyclingLeft : bool ) : ESignType { var signOrder : array<ESignType>; 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 ]; //5+i-1 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() )// && theInput.LastUsedGamepad() )// && ( GetPlayerCombatStance() == PCS_AlertNear || GetPlayerCombatStance() == PCS_Guarded ) ) { 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() ) { /*if ( bLAxisReleased && slideTarget ) { actor = (CActor)slideTarget; if ( actor ) SetCustomRotation( 'Sign', VecHeading( actor.GetWorldPosition() - GetWorldPosition() ), 0.0f, 0.3f, false ); }*/ 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(); //OnProcessCastingOrientation( false ); 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 ); } //if we throw hold while casting sign then the input gets ingored (cleared from combat action buffer when cast sign stop is processed) 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() : array<CBaseGameplayEffect> { return effectManager.GetDrunkMutagens(); } public final function GetPotionBuffs() : array<CBaseGameplayEffect> { return effectManager.GetPotionBuffs(); } public final function RecalcPotionsDurations() { var i : int; var buffs : array<CBaseGameplayEffect>; buffs = GetPotionBuffs(); for(i=0; i<buffs.Size(); i+=1) { 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; } /* private function DrinkMutagenPotion(id : SItemUniqueId, slot : EEquipmentSlots) : bool { var toxicityOffset, toxicitySum : float; var ret : EEffectInteract; var mutagen : SDrunkMutagen; var mutagenParams : SCustomEffectParams; var buffs : array<SEffectInfo>; //var tutState : W3TutorialManagerUIHandlerStatePreparationMutagens; disabled, might be added in patch var result : bool; if(!IsSlotMutagen(slot)) return false; toxicityOffset = CalculateAttributeValue(inv.GetItemAttributeValue(id,'toxicity_offset')); // check what toxicity would be if we drink mutagen, don't allow it to be too high. toxicitySum = abilityManager.GetStat(BCS_Toxicity) + (toxicityOffset - GetMutagenToxicityOffset(slot)) * abilityManager.GetStatMax(BCS_Toxicity); if( toxicitySum > abilityManager.GetStatMax(BCS_Toxicity) ) return false; //buff type inv.GetItemBuffs(id, buffs); //apply mutagen effect mutagenParams.effectType = buffs[0].effectType; mutagenParams.creator = this; mutagenParams.sourceName = "mutagen"; mutagenParams.duration = -1; mutagenParams.customAbilityName = buffs[0].effectAbilityName; ret = AddEffectCustom(mutagenParams); //post-application - if successfull if(ret == EI_Pass || ret == EI_Override || ret == EI_Cumulate) { PlayEffect('use_potion'); itemSlots[slot] = id; //'equip mutagen' mutagen.mutagenName = GetInventory().GetItemName( id ); mutagen.effectType = buffs[0].effectType; mutagen.slot = slot; mutagen.toxicityOffset = toxicityOffset; drunkMutagens.PushBack( mutagen ); AddToxicityOffset(toxicityOffset); result = true; } else { result = false; } / * disabled, might be added in patch //tutorial if(ShouldProcessTutorial('TutorialMutagenPotion')) { tutState = (W3TutorialManagerUIHandlerStatePreparationMutagens)theGame.GetTutorialSystem().uiHandler.GetCurrentState(); if(tutState) { tutState.OnMutagenEquipped(); } } * / //trial of grasses achievement theGame.GetGamerProfile().CheckTrialOfGrasses(); //fundamentals first achievement SetFailedFundamentalsFirstAchievementCondition(true); // report global event theGame.GetGlobalEventsManager().OnScriptedEvent( SEC_OnItemEquipped ); return result; } */ 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); } //calculates final duration of potion (with all skill bonuses) public final function CalculatePotionDuration(item : SItemUniqueId, isMutagenPotion : bool, optional itemName : name) : float { var duration, skillPassiveMod, mutagenSkillMod : float; var val, min, max : SAbilityAttributeValue; //base potion duration 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 function DrinkPreparedPotion( slotid : EEquipmentSlots, optional itemId : SItemUniqueId ) { var i, ind : int; var toxicityOffset, adrenaline : float; var potionToxicity, duration, hpGainValue, maxTox : float; var randomPotions : array<EEffectType>; var effectType : EEffectType; var customAbilityName, factId : name; var ret : EEffectInteract; var atts : array<name>; var effectsOld, effectsNew : array<CBaseGameplayEffect>; var factPotionParams : W3Potion_Fact_Params; var potParams : W3PotionParams; var mutagenParams : W3MutagenBuffCustomParams; var item : SItemUniqueId; var params, potionParams : SCustomEffectParams; var costReduction : SAbilityAttributeValue; //normally use slot BUT you can also drink any potion directly from inventory panel without equipping - in that case we override it by custom itemID if(itemId != GetInvalidUniqueId()) item = itemId; else item = itemSlots[slotid]; //invalid item if(!inv.IsIdValid(item)) return; //potion has no ammo left if( inv.SingletonItemGetAmmo(item) == 0 ) return; //get toxicity costs inv.GetPotionItemBuffData(item, effectType, customAbilityName); maxTox = abilityManager.GetStatMax(BCS_Toxicity); potionToxicity = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity')); toxicityOffset = CalculateAttributeValue(inv.GetItemAttributeValue(item, 'toxicity_offset')); //check for perk which decrases toxicity cost by consuming adrenaline if(CanUseSkill(S_Perk_13)) { costReduction = GetSkillAttributeValue(S_Perk_13, 'cost_reduction', false, true); adrenaline = FloorF(GetStat(BCS_Focus)); costReduction = costReduction * adrenaline; potionToxicity = (potionToxicity - costReduction.valueBase) * (1 - costReduction.valueMultiplicative) - costReduction.valueAdditive; potionToxicity = MaxF(0.f, potionToxicity); } //check toxicity but White Honey can always be drunk if(effectType != EET_WhiteHoney) { if(abilityManager.GetStat(BCS_Toxicity, false) + potionToxicity + toxicityOffset > maxTox ) return; } //buff info customAbilityName = ''; inv.GetPotionItemBuffData(item, effectType, customAbilityName); //custom params - fact name if(effectType == EET_Fact) { inv.GetItemAttributes(item, atts); for(i=0; i<atts.Size(); i+=1) { 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; } //custom params for mutagens else if(inv.ItemHasTag( item, 'Mutagen' )) { mutagenParams = new W3MutagenBuffCustomParams in theGame; mutagenParams.toxicityOffset = toxicityOffset; mutagenParams.potionItemName = inv.GetItemName(item); potionParams.buffSpecificParams = mutagenParams; } //custom params for potions else { potParams = new W3PotionParams in theGame; potParams.potionItemName = inv.GetItemName(item); potionParams.buffSpecificParams = potParams; } //set duration duration = CalculatePotionDuration(item, inv.ItemHasTag( item, 'Mutagen' )); //apply potion potionParams.effectType = effectType; potionParams.creator = this; potionParams.sourceName = "drank_potion"; potionParams.duration = duration; potionParams.customAbilityName = customAbilityName; ret = AddEffectCustom(potionParams); //clear custom params if(factPotionParams) delete factPotionParams; if(mutagenParams) delete mutagenParams; //use up ammo inv.SingletonItemRemoveAmmo(item); //post-application - if successfull if(ret == EI_Pass || ret == EI_Override || ret == EI_Cumulate) { abilityManager.GainStat(BCS_Toxicity, potionToxicity ); //adrenaline perk if(CanUseSkill(S_Perk_13)) { abilityManager.DrainFocus(adrenaline); } if (!IsEffectActive('invisible')) { PlayEffect('use_potion'); } if ( inv.ItemHasTag( item, 'Mutagen' ) ) { //trial of grasses achievement theGame.GetGamerProfile().CheckTrialOfGrasses(); //fundamentals first achievement SetFailedFundamentalsFirstAchievementCondition(true); } //heal 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); } //bonus random potion if(CanUseSkill(S_Alchemy_s04) && !skillBonusPotionEffect && (RandF() < CalculateAttributeValue(GetSkillAttributeValue(S_Alchemy_s04, 'apply_chance', false, true)) * GetSkillLevel(S_Alchemy_s04))) { //list of potions to pick from randomPotions.PushBack(EET_BlackBlood); randomPotions.PushBack(EET_Blizzard); randomPotions.PushBack(EET_Cat); 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.PushBack(EET_WhiteRaffardDecoction); //exclude current potion randomPotions.Remove(effectType); ind = RandRange(randomPotions.Size()); 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=0; i<effectsNew.Size(); i+=1) { if(!effectsOld.Contains(effectsNew[i])) { ind = i; break; } } if(ind > -1) { skillBonusPotionEffect = effectsNew[ind]; } } } } theGame.GetGamerProfile().SetStat(ES_ActivePotions, effectManager.GetPotionBuffsCount()); } theTelemetry.LogWithLabel(TE_ELIXIR_USED, inv.GetItemName(item)); if(ShouldProcessTutorial('TutorialPotionAmmo')) { FactsAdd("tut_used_potion"); } SetFailedFundamentalsFirstAchievementCondition(true); } // Caches recipes' data from XML for given recipes private function BonusPotionGetDurationFromXML(type : EEffectType) : float { var dm : CDefinitionsManagerAccessor; var main, ingredients : SCustomNode; var tmpName, typeName, itemName : name; var abs : array<name>; var min, max : SAbilityAttributeValue; var tmpInt : int; var temp : array<float>; var i, temp2, temp3 : int; dm = theGame.GetDefinitionsManager(); main = dm.GetCustomDefinition('alchemy_recipes'); typeName = EffectTypeToName(type); //get potion item name for(i=0; i<main.subNodes.Size(); i+=1) { if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'type_name', tmpName)) { //proper potion definition... if(tmpName == typeName) { if(dm.GetCustomNodeAttributeValueInt(main.subNodes[i], 'level', tmpInt)) { //of level 1... if(tmpInt == 1) { if(dm.GetCustomNodeAttributeValueName(main.subNodes[i], 'cookedItem_name', itemName)) { //got valid item id if(IsNameValid(itemName)) { break; } } } } } } } if(!IsNameValid(itemName)) return 0; //get duration from item's ability's definition 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; } //////////////////////////////////////////////////////////////////////////////// // // @Buffs // //////////////////////////////////////////////////////////////////////////////// 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<CBaseGameplayEffect> { var null : array<CBaseGameplayEffect>; 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; } /* 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 { //if has quen and gets DOT - abort DOT's anim 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; } //////////////////////////////////////////////////////////////////////////////// // // @Stats // //////////////////////////////////////////////////////////////////////////////// event OnLevelGained(currentLevel : int, show : bool) { var hud : CR4ScriptedHud; hud = (CR4ScriptedHud)theGame.GetHud(); if(abilityManager && abilityManager.IsInitialized()) { ((W3PlayerAbilityManager)abilityManager).OnLevelGained(currentLevel); } if ( theGame.GetDifficultyMode() != EDM_Hardcore ) { Heal(GetStatMax(BCS_Vitality)); } //achievement if(currentLevel >= 35) { theGame.GetGamerProfile().AddAchievement(EA_Immortal); } if ( hud && currentLevel < 70 ) { 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<name>; 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; } } } //used by Ignore Pain skill to change max vitality based on dynamically calculated value (cannot use abilities to do that) 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' ); //MSTODO: //SetMoveTarget( FindNearestTarget() ); FindMoveTarget(); SetCanPlayHitAnim( true ); this.SetBIsCombatActionAllowed( true ); if ( this.GetFinisherVictim() && this.GetFinisherVictim().HasAbility( 'ForceFinisher' ) ) { this.GetFinisherVictim().SignalGameplayEvent( 'Finisher' ); } else if (this.BufferCombatAction != EBAT_EMPTY ) { //if ( !( this.BufferCombatAction == EBAT_CastSign ) )//&& inv.IsItemCrossbow( inv.GetItemFromSlot( 'l_weapon' ) ) ) ) //LogChannel('combatActionAllowed',"BufferCombatAction != EBAT_EMPTY"); if ( !IsCombatMusicEnabled() ) { SetCombatActionHeading( ProcessCombatActionHeading( this.BufferCombatAction ) ); FindTarget(); UpdateDisplayTarget( true ); } if ( AllowAttack( GetTarget(), this.BufferCombatAction ) ) this.ProcessCombatActionBuffer(); } else { //stamina pause should happen just for a brief moment ResumeEffects(EET_AutoStaminaRegen, 'InsideCombatAction'); //if sign button is held we should cast sign to have better responsiveness /*if ( theInput.GetActionValue( 'CastSignHold' ) > 0.f ) //GetCombatAction() != EBAT_CastSign && { this.PushCombatActionOnBuffer( EBAT_CastSign, BS_Pressed); this.ProcessCombatActionBuffer(); }*/ } } 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; } } public function IsInCombatAction_SpecialAttack() : bool { if ( IsInCombatAction() && ( GetCombatAction() == EBAT_SpecialAttack_Light || 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(); } //--------------------------------- RADIAL MENU #B -------------------------------------- timer function OpenRadialMenu( time: float, id : int ) { //_gfxFuncShowRadialMenu(FlashArgBool(true)); if( GetBIsCombatActionAllowed() && !IsUITakeInput() ) { bShowRadialMenu = true; } //LogChannel('RADIAL',"OpenRadialMenu timer"); this.RemoveTimer('OpenRadialMenu'); } public function OnAddRadialMenuOpenTimer( ) { //LogChannel('RADIAL',"OnAddRadialMenuOpenTimer"); //if( GetBIsCombatActionAllowed() ) //{ // fix to make radial menu delay independent of current time scale // if it's required in other places as well, changes in timer would be more appropriate this.AddTimer('OpenRadialMenu', _HoldBeforeOpenRadialMenuTime * theGame.GetTimeScale() ); //} } public function SetShowRadialMenuOpenFlag( bSet : bool ) { //LogChannel('RADIAL',"OnAddRadialMenuOpenTimer bSet "+bSet); bShowRadialMenu = bSet; } public function OnRemoveRadialMenuOpenTimer() { //LogChannel('RADIAL',"OnRemoveRadialMenuOpenTimer"); this.RemoveTimer('OpenRadialMenu'); } public function ResetRadialMenuOpenTimer() { //LogChannel('RADIAL',"ResetRadialMenuOpenTimer"); this.RemoveTimer('OpenRadialMenu'); if( GetBIsCombatActionAllowed() ) { // fix to make radial menu delay independent of current time scale // if it's required in other places as well, changes in timer would be more appropriate AddTimer('OpenRadialMenu', _HoldBeforeOpenRadialMenuTime * theGame.GetTimeScale() ); } } //--------------------------------- Companion Module #B -------------------------------------- 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; } //-------------------------------------- OTHER --------------------------------------------- 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 { //usable item and crossbow ThrowingAbort(); } } //special item with chance to apply quen when hit with projectile 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(); } } } //abort meditation unless it's toxicity damage if( !((W3Effect_Toxicity)damageAction.causer) ) MeditationForceAbort(true); //if in whirlwind, skip hit animations if(IsDoingSpecialAttack(false)) damageAction.SetHitAnimationPlayType(EAHA_ForceNo); return super.ReactToBeingHit(damageAction, buffNotApplied); } protected function ShouldPauseHealthRegenOnHit() : bool { //level 3 swallow prevents regen pause if( (HasBuff(EET_Swallow) && GetPotionBuffLevel(EET_Swallow) >= 3) || HasBuff(EET_Runeword8) ) 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(); } //HAX_SignToThrowItemRestore(); } event OnBlockingSceneStarted( scene: CStoryScene ) { var med : W3PlayerWitcherStateMeditationWaiting; //abort meditation if meditating med = (W3PlayerWitcherStateMeditationWaiting)GetCurrentState(); if(med) { med.StopRequested(true); } //---=== modFriendlyHUD ===--- EndExplorationMeditation(); //---=== modFriendlyHUD ===--- //super has to be called as last since it changes player state super.OnBlockingSceneStarted( scene ); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// ---=== @HORSE ===--- //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public function GetHorseManager() : W3HorseManager { return (W3HorseManager)EntityHandleGet( horseManagerHandle ); } //Provide item id from HORSE'S INVENTORY. Returns false if failed. public function HorseEquipItem(horsesItemId : SItemUniqueId) : bool { var man : W3HorseManager; man = GetHorseManager(); if(man) return man.EquipItem(horsesItemId) != GetInvalidUniqueId(); return false; } //Returns false if failed public function HorseUnequipItem(slot : EEquipmentSlots) : bool { var man : W3HorseManager; man = GetHorseManager(); if(man) return man.UnequipItem(slot) != GetInvalidUniqueId(); return false; } //returns removed amount public final function HorseRemoveItemByName(itemName : name, quantity : int) { var man : W3HorseManager; man = GetHorseManager(); if(man) man.HorseRemoveItemByName(itemName, quantity); } //returns removed amount public final function HorseRemoveItemByCategory(itemCategory : name, quantity : int) { var man : W3HorseManager; man = GetHorseManager(); if(man) man.HorseRemoveItemByCategory(itemCategory, quantity); } //returns removed amount 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; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// ---=== @TUTORIAL ===--- ///////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public final function TutorialMutagensUnequipPlayerSkills() : array<STutorialSavedSkill> { 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<STutorialSavedSkill>) { var pam : W3PlayerAbilityManager; pam = (W3PlayerAbilityManager)abilityManager; return pam.TutorialMutagensCleanupTempSkills(savedEquippedSkills); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// ---=== @STATS ===--- //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public function GetOffenseStatsList() : 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 : 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.steelFastCritDmg *= 100; 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.steelStrongCritDmg *= 100; 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.silverFastCritDmg *= 100; 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.silverStrongCritDmg *= 100; playerOffenseStats.crossbowCritChance = CalculateAttributeValue(GetAttributeValue(theGame.params.CRITICAL_HIT_CHANCE)); if (CanUseSkill(S_Sword_s07)) playerOffenseStats.crossbowCritChance += CalculateAttributeValue(GetSkillAttributeValue(S_Sword_s07, theGame.params.CRITICAL_HIT_CHANCE, false, true)) * GetSkillLevel(S_Sword_s07); // Bolt stats playerOffenseStats.crossbowSteelDmgType = theGame.params.DAMAGE_NAME_PIERCING; if (GetItemEquippedOnSlot(EES_Bolt, item)) { //GetItemEquippedOnSlot(EES_RangedWeapon, crossbow); 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; } } } // Crossbow 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); } 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 : float; var repairObjectBonus : SAbilityAttributeValue; durMod = 0; damage = super.GetTotalWeaponDamage(weaponId, damageTypeName, crossbowId); //durability & repair bonus only affects physical damage 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 has durability at all if(durRatio >= 0) durMod = theGame.params.GetDurabilityMultiplier(durRatio, true); else durMod = 1; } return damage * (durMod + repairObjectBonus.valueMultiplicative); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// ---=== @SKILLS ===--- /////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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 GetBoughtSkillLevel(s : ESkill) : int { if(abilityManager && abilityManager.IsInitialized()) return ((W3PlayerAbilityManager)abilityManager).GetBoughtSkillLevel(s); return -1; } //used mostly for dialog choice options 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); } //removes temporarily gained skills public function RemoveTemporarySkills() { var i : int; var pam : W3PlayerAbilityManager; if(tempLearnedSignSkills.Size() > 0) { pam = (W3PlayerAbilityManager)abilityManager; for(i=0; i<tempLearnedSignSkills.Size(); i+=1) { 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; } //add temporarily all skills for 'All Out' skill 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 GetSkillLinkColorVertical(skill : ESkill, out color : ESkillColor, out isJoker : bool) { if(abilityManager && abilityManager.IsInitialized()) ((W3PlayerAbilityManager)abilityManager).GetSkillLinkColorVertical(skill, color, isJoker); } public function GetSkillLinkColorLeft(skill : ESkill, out color : ESkillColor, out isJoker : bool) { if(abilityManager && abilityManager.IsInitialized()) ((W3PlayerAbilityManager)abilityManager).GetSkillLinkColorLeft(skill, color, isJoker); } public function GetSkillLinkColorRight(skill : ESkill, out color : ESkillColor, out isJoker : bool) { if(abilityManager && abilityManager.IsInitialized()) ((W3PlayerAbilityManager)abilityManager).GetSkillLinkColorRight(skill, color, isJoker); }*/ public function HasAlternateQuen() : bool { var quenEntity : W3QuenEntity; quenEntity = (W3QuenEntity)GetCurrentSignEntity(); if(quenEntity) { return quenEntity.IsAlternateCast(); } return false; } /////////////////////////////////////////////////////////////////////// ////////////////// @LEVELING @EXPERIENCE //////////////////////////// /////////////////////////////////////////////////////////////////////// public function AddPoints(type : ESpendablePointType, amount : int, show : bool) { levelManager.AddPoints(type, amount, show); } public function GetLevel() : int {return levelManager.GetLevel();} 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)); } //////////////////////////////////////////////////////////////////////////// //////////////////// @SIGNS ////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private saved var runewordInfusionType : ESignType; default runewordInfusionType = ST_None; public final function GetRunewordInfusionType() : ESignType { return runewordInfusionType; } public function OnSignCastPerformed(signType : ESignType, isAlternate : bool) { var items : array<SItemUniqueId>; var weaponEnt : CEntity; var fxName : name; 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]); //clear previous infusion fx weaponEnt.StopEffect('runeword_aard'); weaponEnt.StopEffect('runeword_axii'); weaponEnt.StopEffect('runeword_igni'); weaponEnt.StopEffect('runeword_quen'); weaponEnt.StopEffect('runeword_yrden'); //show current fx 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); } } public saved var savedQuenHealth, savedQuenDuration : float; //this is insane! but there's no event on saving game 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) { var quen : W3QuenEntity; quen = (W3QuenEntity)GetSignEntity(ST_Quen); if(quen) quen.ForceFinishQuen(skipVisuals); } //returns value of spell power to be used by this sign (including power bonuses) public function GetTotalSignSpellPower(signSkill : ESkill) : SAbilityAttributeValue { var sp : SAbilityAttributeValue; var penalty : SAbilityAttributeValue; var penaltyReduction : float; var penaltyReductionLevel : int; //character SP + spell specific skills sp = GetSkillAttributeValue(signSkill, PowerStatEnumToName(CPS_SpellPower), true, true); //skill custom if ( signSkill == S_Magic_s01 ) { //wave leveling penalty reduction 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; //add amount equal to penalty reduction (since full penalty is already applied) } } //magic item abilities 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'); } return sp; } //////////////////////////////////////////////////////////////////////////// ///////////////////////// @GWENT ///////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public final function GetGwentCardIndex( cardName : name ) : int { var dm : CDefinitionsManagerAccessor; dm = theGame.GetDefinitionsManager(); if(dm.ItemHasTag( cardName , 'GwintCardLeader' )) //Checks for Gwent cards factions { 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 , '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; //getting new gwent card tutorial - cannot be done in quest as there is no way to send signal //to that phase if player activated it before patch 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(); } else { return false; } 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' )) //Checks for Gwent cards factions { cardIndex = theGame.GetGwintManager().GwentLeadersNametoInt( cardName ); for(i=0; i<amount; i+=1) theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardNrkd' )) { cardIndex = theGame.GetGwintManager().GwentNrkdNameToInt( cardName ); for(i=0; i<amount; i+=1) theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardNlfg' )) { cardIndex = theGame.GetGwintManager().GwentNlfgNameToInt( cardName ); for(i=0; i<amount; i+=1) theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardSctl' )) { cardIndex = theGame.GetGwintManager().GwentSctlNameToInt( cardName ); for(i=0; i<amount; i+=1) theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardMstr' )) { cardIndex = theGame.GetGwintManager().GwentMstrNameToInt( cardName ); for(i=0; i<amount; i+=1) theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardNeutral' )) { cardIndex = theGame.GetGwintManager().GwentNeutralNameToInt( cardName ); for(i=0; i<amount; i+=1) theGame.GetGwintManager().RemoveCardFromCollection( cardIndex ); } else if(dm.ItemHasTag( cardName , 'GwintCardSpcl' )) { cardIndex = theGame.GetGwintManager().GwentSpecialNameToInt( cardName ); for(i=0; i<amount; i+=1) 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(); } else { return false; } 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" ); } } } //////////////////////////////////////////////////////////////////////////// //////////////////// @MEDITATION ///////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public function SimulateBuffTimePassing(simulatedTime : float) { super.SimulateBuffTimePassing(simulatedTime); FinishQuen(true); } //Can player kneel and enter meditation mode. Does NOT check for 'waiting' mechanics public function CanMeditate() : bool { var currentStateName : name; currentStateName = GetCurrentStateName(); //cannot play kneel animation if(currentStateName == 'Exploration' && !CanPerformPlayerAction()) return false; //not in exloration or meditation if(GetCurrentStateName() != 'Exploration' && GetCurrentStateName() != 'Meditation' && GetCurrentStateName() != 'MeditationWaiting') return false; //not in vehicles if(GetUsedVehicle()) return false; //not if in water return CanMeditateHere(); } //If the 'waiting' mechanic is available public final function CanMeditateWait(optional skipMeditationStateCheck : bool) : bool { var currState : name; currState = GetCurrentStateName(); //if not meditating then cannot meditate wait. Also hack for exploration - if game time is paused by menus we might not have had //enough time to enter meditation state, and are frozen inbetween if(!skipMeditationStateCheck && currState != 'Meditation') return false; //if time stopped cannot meditate as time does not flow at all if(theGame.IsGameTimePaused()) return false; if(!IsActionAllowed( EIAB_MeditationWaiting )) return false; //---=== modFriendlyHUD ===--- return CanMeditateHere(); //---=== modFriendlyHUD ===--- } //Is current position ok for kneeling to meditate 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; //---=== modFriendlyHUD ===--- if ( GetFHUDConfig().fireplaceOnly ) { campFireEnt = NULL; foundCampFire = FindCampFire(); return foundCampFire; } //---=== modFriendlyHUD ===--- return true; } //---=== modFriendlyHUD ===--- private function FindCampFire() : bool { var entities : array< CGameplayEntity >; var glComponent : CGameplayLightComponent; var i : int; if ( GetFHUDConfig().campFireOnly ) { FindGameplayEntitiesInRange( entities, thePlayer, 1.5, 10,, FLAG_ExcludePlayer,, 'W3Campfire' ); } else { FindGameplayEntitiesInRange( entities, thePlayer, 1.5, 10,, FLAG_ExcludePlayer,, 'CGameplayEntity' ); } for ( i = 0; i < entities.Size(); i += 1 ) { glComponent = (CGameplayLightComponent)entities[i].GetComponentByClassName( 'CGameplayLightComponent' ); if ( glComponent ) { if ( glComponent.IsLightOn() ) { campFireEnt = entities[i]; return true; } } } return false; } //---=== modFriendlyHUD ===--- //Makes player kneel and enter meditation. Does not WAIT any time yet public function Meditate() { var medState : W3PlayerWitcherStateMeditation; if (!CanMeditate() || GetCurrentStateName() == 'Meditation' || GetCurrentStateName() == 'MeditationWaiting') return; GotoState('Meditation'); medState = (W3PlayerWitcherStateMeditation)GetState('Meditation'); medState.SetMeditationPointHeading(GetHeading()); } //---=== modFriendlyHUD ===--- //healhs health, restores alchemy items public final function MeditationRestoring(simulatedTime : float) // this function is used by regular meditation menu { abilityManager.DrainToxicity( abilityManager.GetStat( BCS_Toxicity ) ); // this sets toxicity to zero abilityManager.DrainFocus( abilityManager.GetStat( BCS_Focus ) ); // this sets adrenaline to zero SimulateBuffTimePassing( simulatedTime ); // simulatedTime is not actually used, all effects are just nullified MeditationRegenFullHealth(); // this restores full health MeditationRefill( GetFHUDConfig().REFILL_INTERVAL_SECONDS ); // this refills all potions if ( GetFHUDConfig().resetRefillSettingToDefaultAfterMeditation ) { GetFHUDConfig().ResetRefillPotionsWhileMeditating(); } } public function MeditationRefill( gameTimeSecs : float ) : bool { if ( gameTimeSecs >= GetFHUDConfig().REFILL_INTERVAL_SECONDS && GetFHUDConfig().refillPotionsWhileMeditatingToggle ) { inv.SingletonItemsRefillAmmo(); return true; } return false; } public function UpdateEffectsAccelerated( realTimeSecs, acceleration : float ) { effectManager.PerformUpdate( realTimeSecs * acceleration ); } public function MeditationRegenFullHealth() { if ( theGame.GetDifficultyMode() != EDM_Hard && theGame.GetDifficultyMode() != EDM_Hardcore || GetFHUDConfig().fullHealthRegenAnyDifficulty ) { Heal(GetStatMax(BCS_Vitality)); } } timer function ExplorationMeditationTimer(dt : float, id : int) { StartExplorationMeditation(); } public function StartExplorationMeditation() { if ( GetCurrentStateName() != 'ExplorationMeditation' ) { if ( CanMeditateWait( true ) ) { PushState( 'ExplorationMeditation' ); } else { DisplayHudMessage( GetLocStringByKeyExt( "menu_cannot_perform_action_here" ) ); } } } public function EndExplorationMeditation() { if ( GetCurrentStateName() == 'ExplorationMeditation' ) { PopState(); } } //---=== modFriendlyHUD ===--- 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); } } //because UI handles meditation differently right now, we no longer enter Meditation when entering panel and //when waiting the game is not running (no ticks) if(forceCloseUI && theGame.GetGuiManager().IsAnyMenu()) { theGame.GetGuiManager().GetRootMenu().CloseMenu(); DisplayActionDisallowedHudMessage(EIAB_MeditationWaiting, false, false, true, false); } //---=== modFriendlyHUD ===--- EndExplorationMeditation(); //---=== modFriendlyHUD ===--- } 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'); //fx has typo in name } var runeword10TriggerredOnFinisher, runeword12TriggerredOnFinisher : bool; event OnFinisherStart() { super.OnFinisherStart(); runeword10TriggerredOnFinisher = false; runeword12TriggerredOnFinisher = false; } //////////////////////////////////////////////////////////////////////////// //////////////////// @DEBUG ////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public function CheatResurrect() { super.CheatResurrect(); theGame.ReleaseNoSaveLock(theGame.deathSaveLockId); theInput.RestoreContext( 'Exploration', true ); } //testing skills equip public function Debug_EquipTestingSkills(equip : bool, force : bool) { var skills : array<ESkill>; var i, slot : int; //make pam believe it's level 36 so it unlocks skill slots ((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); //equip special skills if(equip) { for(i=0; i<skills.Size(); i+=1) { if(!force && IsSkillEquipped(skills[i])) continue; //add skill if(GetSkillLevel(skills[i]) == 0) AddSkill(skills[i]); //find free slot if(force) slot = i+1; //slots are numbered 1+ not 0+ else slot = GetFreeSkillSlot(); //equip EquipSkill(skills[i], slot); } } else { for(i=0; i<skills.Size(); i+=1) { 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<SItemUniqueId>; var abs : array<name>; delete abilityManager; delete levelManager; delete effectManager; //remove old abilities abs = GetAbilities(false); for(i=0; i<abs.Size(); i+=1) RemoveAbility(abs[i]); //get default abilities and add them abs.Clear(); GetCharacterStatsParam(abs); for(i=0; i<abs.Size(); i+=1) AddAbility(abs[i]); //leveling levelManager = new W3LevelManager in this; levelManager.Initialize(); levelManager.PostInit(this, false); //skills, perks etc., exp, buffs AddAbility('GeraltSkills_Testing'); 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 //Debug_EquipTestingSkills(false); //-------------------------------------- ITEMS //remove items if(!keepInv) { inv.RemoveAllItems(); } //add default items 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(); //equip items inv.GetAllItems(items); for(i=0; i<items.Size(); i+=1) { if(!inv.ItemHasTag(items[i], 'NoDrop')) //skip body parts EquipItem(items[i]); } //items from testing inventory entity Debug_GiveTestingItems(0); } 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 { return levelupAbilities[ id ]; } 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; } // Purpose of this command is ONLY to allow to continue testing on saves with broken horse manager // DO NOT USE IT OTHERWISE 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; } //private saved var blockedSigns : array<ESignType>; /*public final function BlockSignSelection(signType : ESignType, block : bool) { if(block && !blockedSigns.Contains(signType)) blockedSigns.PushBack(signType); else if(!block) blockedSigns.Remove(signType); }*/ /*public final function GetBlockedSigns () : array<ESignType> { return blockedSigns; }*/ 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; //return blockedSigns.Contains(signType); } public final function AddAnItemWithAutogenLevelAndQuality(itemName : name, desiredLevel : int, minQuality : int, optional equipItem : bool) { var itemLevel, quality : int; var ids : array<SItemUniqueId>; 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 not doable at all 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<SItemUniqueId>; var attemptCounter : int; itemLevel = 0; while(itemLevel != desiredLevel) { attemptCounter += 1; ids.Clear(); ids = inv.AddAnItem(itemName, 1, true); itemLevel = inv.GetItemLevel(ids[0]); //if not doable at all 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<SItemUniqueId>; 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 not doable at all if(attemptCounter >= 1000) break; if(quality < minQuality) inv.RemoveItem(ids[0]); } if(equip) EquipItem(ids[0]); } public final function StandaloneEp1_1() { var i, inc, quantityLow, randLow, quantityMedium, randMedium, quantityHigh, randHigh, startingMoney : int; var pam : W3PlayerAbilityManager; var ids : array<SItemUniqueId>; var STARTING_LEVEL : int; FactsAdd("StandAloneEP1", 1); //clear inventory inv.RemoveAllItems(); //add required quest items inv.AddAnItem('Illusion Medallion', 1, true, true, false); inv.AddAnItem('q103_safe_conduct', 1, true, true, false); //remove all achievements theGame.GetGamerProfile().ClearAllAchievementsForEP1(); //set level STARTING_LEVEL = 32; inc = STARTING_LEVEL - GetLevel(); for(i=0; i<inc; i+=1) { levelManager.AddPoints(EExperiencePoint, levelManager.GetTotalExpForNextLevel() - levelManager.GetPointsTotal(EExperiencePoint), false); } //release all skillpoints levelManager.ResetCharacterDev(); pam = (W3PlayerAbilityManager)abilityManager; if(pam) { pam.ResetCharacterDev(); } levelManager.SetFreeSkillPoints(levelManager.GetLevel() - 1 + 11); //+1 for q111 quest reward, +10 because balancing //mutagen ings 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); //money startingMoney = 20000; if(GetMoney() > startingMoney) { RemoveMoney(GetMoney() - startingMoney); } else { AddMoney( 20000 - GetMoney() ); } //armor /* inv.AddAnItem('Light armor 01r'); inv.AddAnItem('Boots 04'); inv.AddAnItem('Gloves 04'); inv.AddAnItem('Pants 04'); AddAnItemWithMinQuality('Medium armor 05r', 3, true); AddAnItemWithMinQuality('Boots 032', 3, true); AddAnItemWithMinQuality('Heavy gloves 02', 3, true); AddAnItemWithMinQuality('Pants 03', 3, true); inv.AddAnItem('Heavy armor 05r'); inv.AddAnItem('Heavy boots 08'); inv.AddAnItem('Heavy gloves 04'); inv.AddAnItem('Heavy pants 04'); //swords AddAnItemWithMinQuality('Gnomish sword 2', 3, true); AddAnItemWithMinQuality('Azurewrath', 3, true); */ //armor 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]); //swords 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]); //torch inv.AddAnItem('Torch', 1, true, true, false); //crafting ingredients 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); //crossbow, bolts 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); //remove recipes RemoveAllAlchemyRecipes(); RemoveAllCraftingSchematics(); //recipes - potions //AddAlchemyRecipe('Recipe for Black Blood 1'); //AddAlchemyRecipe('Recipe for Blizzard 1'); AddAlchemyRecipe('Recipe for Cat 1'); //AddAlchemyRecipe('Recipe for Full Moon 1'); //AddAlchemyRecipe('Recipe for Golden Oriole 1'); //AddAlchemyRecipe('Recipe for Killer Whale 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 Thunderbolt 1'); AddAlchemyRecipe('Recipe for White Gull 1'); AddAlchemyRecipe('Recipe for White Honey 1'); AddAlchemyRecipe('Recipe for White Raffards Decoction 1'); /* AddAlchemyRecipe('Recipe for Black Blood 2'); AddAlchemyRecipe('Recipe for Blizzard 2'); AddAlchemyRecipe('Recipe for Cat 2'); AddAlchemyRecipe('Recipe for Full Moon 2'); AddAlchemyRecipe('Recipe for Golden Oriole 2'); AddAlchemyRecipe('Recipe for Killer Whale 2'); AddAlchemyRecipe('Recipe for Maribor Forest 2'); AddAlchemyRecipe('Recipe for Petris Philtre 2'); AddAlchemyRecipe('Recipe for Swallow 2'); AddAlchemyRecipe('Recipe for Tawny Owl 2'); AddAlchemyRecipe('Recipe for Thunderbolt 2'); AddAlchemyRecipe('Recipe for White Gull 2'); AddAlchemyRecipe('Recipe for White Honey 2'); AddAlchemyRecipe('Recipe for White Raffards Decoction 2'); */ //recipes - oils 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'); //recipes - bombs AddAlchemyRecipe('Recipe for Dancing Star 1'); //AddAlchemyRecipe('Recipe for Devils Puffball 1'); AddAlchemyRecipe('Recipe for Dwimeritum Bomb 1'); //AddAlchemyRecipe('Recipe for Dragons Dream 1'); AddAlchemyRecipe('Recipe for Grapeshot 1'); AddAlchemyRecipe('Recipe for Samum 1'); //AddAlchemyRecipe('Recipe for Silver Dust Bomb 1'); AddAlchemyRecipe('Recipe for White Frost 1'); /* AddAlchemyRecipe('Recipe for Dancing Star 2'); AddAlchemyRecipe('Recipe for Devils Puffball 2'); AddAlchemyRecipe('Recipe for Dwimeritum Bomb 2'); AddAlchemyRecipe('Recipe for Dragons Dream 2'); AddAlchemyRecipe('Recipe for Grapeshot 2'); AddAlchemyRecipe('Recipe for Samum 2'); AddAlchemyRecipe('Recipe for Silver Dust Bomb 2'); AddAlchemyRecipe('Recipe for White Frost 2'); */ //recipes - alcohol AddAlchemyRecipe('Recipe for Dwarven spirit 1'); AddAlchemyRecipe('Recipe for Alcohest 1'); AddAlchemyRecipe('Recipe for White Gull 1'); //crafting recipes AddStartingSchematics(); //cooked alchemy items 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'); //mutagen decoctions inv.AddAnItem('Mutagen 17'); //forktail inv.AddAnItem('Mutagen 19'); //wraith inv.AddAnItem('Mutagen 27'); //griphon inv.AddAnItem('Mutagen 26'); //leshen //repair kits 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); //runes 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); //memory exhaust error StandaloneEp1_2(); } public final function StandaloneEp1_2() { var horseId : SItemUniqueId; var ids : array<SItemUniqueId>; var ents : array< CJournalBase >; var i : int; var manager : CWitcherJournalManager; //food inv.AddAnItem( 'Cows milk', 20 ); ids.Clear(); ids = inv.AddAnItem( 'Dumpling', 44 ); EquipItem(ids[0]); //clearing potion inv.AddAnItem('Clearing Potion', 2, true, false, false); //horse gear 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(); //delete journal entries - bestiary manager.GetActivatedOfType( 'CJournalCreature', ents ); for(i=0; i<ents.Size(); i+=1) { manager.ActivateEntry(ents[i], JS_Inactive, false, true); } //delete journal entries - characters ents.Clear(); manager.GetActivatedOfType( 'CJournalCharacter', ents ); for(i=0; i<ents.Size(); i+=1) { manager.ActivateEntry(ents[i], JS_Inactive, false, true); } //delete journal entries - quest ents.Clear(); manager.GetActivatedOfType( 'CJournalQuest', ents ); for(i=0; i<ents.Size(); i+=1) { //don't disable EP1 quest if( StrStartsWith(ents[i].baseName, "q60")) continue; manager.ActivateEntry(ents[i], JS_Inactive, false, true); } //tutorial entries activate 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); //disable quest blocks with tutorials FactsAdd('kill_base_tutorials'); //disable already queued tutorials theGame.GetTutorialSystem().RemoveAllQueuedTutorials(); //enable start of standalone mode tutorial FactsAdd('standalone_ep1'); FactsRemove("StandAloneEP1"); theGame.GetJournalManager().ForceUntrackingQuestForEP1Savegame(); } function Debug_FocusBoyFocusGain() { var focusGain : float; focusGain = FactsQuerySum("debug_fact_focus_boy") ; GainStat(BCS_Focus, focusGain ); } } exec function fuqfep1() { theGame.GetJournalManager().ForceUntrackingQuestForEP1Savegame(); } /////////////////////////////////////////////////////////////////////// // HACKS! DO NOT USE THIS!!! IF IT IS REAAALY NEEDED ASK BEFORE USING!!!! - MAREK /////////////////////////////////////////////////////////////////////// function GetWitcherPlayer() : W3PlayerWitcher { return (W3PlayerWitcher)thePlayer; } Link to comment Share on other sites More sharing options...
tbellovics Posted November 6, 2015 Share Posted November 6, 2015 Hello, Did you merged the playerwitcher.ws file with the Script Merger? Was there any unresolvable conflicts that was done by manually merging?It seems you lost a } Try to open the merged version of the script (Wither 3 directory\mods\mod_000merged\content\scripts\game\player\playerwitcher.ws or something like this) in notepad and add the } bracket at the end. something like this (the red one is the newly added): function Debug_FocusBoyFocusGain() { var focusGain : float; focusGain = FactsQuerySum("debug_fact_focus_boy") ; GainStat(BCS_Focus, focusGain ); }}} exec function fuqfep1(){ theGame.GetJournalManager().ForceUntrackingQuestForEP1Savegame();} ///////////////////////////////////////////////////////////////////////// HACKS! DO NOT USE THIS!!! IF IT IS REAAALY NEEDED ASK BEFORE USING!!!! - MAREK/////////////////////////////////////////////////////////////////////// function GetWitcherPlayer() : W3PlayerWitcher{ return (W3PlayerWitcher)thePlayer;} I'm unable to test it for you now, but maybe it solves your issue. Link to comment Share on other sites More sharing options...
KaeyShi Posted February 13, 2016 Share Posted February 13, 2016 i had the same error, which i resolved in closing the file with }. now i get a new error:Error [mod0000_mergedfiles]game\player\playerwitcher.ws(7734): Exec function 'fuqfep1' cannot be declared inside a class. can anyone help? please? Link to comment Share on other sites More sharing options...
xshadow87x Posted September 4, 2016 Share Posted September 4, 2016 bump Link to comment Share on other sites More sharing options...
NorthernHare Posted October 12, 2017 Share Posted October 12, 2017 (edited) I have a similiar error: Error [mod0000_mergedfiles]game\gui\main_menu\ingamemenu.ws(2155): Unexpected end of file found after '{' at line 65 I attach txt version of the file because i can't attach the original Edited October 12, 2017 by NorthernHare Link to comment Share on other sites More sharing options...
Atilla2281 Posted December 14, 2017 Share Posted December 14, 2017 (edited) //---=== modPreparations ===--- statemachine class W3PlayerWitcher extends CR4Player} <<Anyone can help me with this? Error [mod0000_mergedfiles]game\player\playerwitcher.ws(66): Found unexpected '}'//---=== modPreparations ===---var foundOpenFire : bool;var openFireEnt : CGameplayEntity;var spawnedCampFire : W3Campfire;var prepConfig : CModPreparationsConfig;var prepError : EPrepError;//---=== modPreparations ===---//modSOR_Speed++ private var cSpeedMult : float; default cSpeedMult = 1.0f; //modSOR_Speed--//modSOR_Bolts++ private saved var BoltsOff :int; default BoltsOff = 0;private var noBoltsArmors : array<name>; //modSOR_Bolts-- //modSOR_Cloak++ private saved var CloakOff :int; default CloakOff = 0; Anyone can help me with this?Error [mod0000_mergedfiles]game\player\playerwitcher.ws(66): Found unexpected '}' Edited December 14, 2017 by Atilla2281 Link to comment Share on other sites More sharing options...
b1lal545 Posted April 27, 2018 Share Posted April 27, 2018 https://hastebin.com/zecipahato.php Hi, guys. I'm getting the same type of error and I have no idea where the bracket placement should be.It says, unexpected end of file found on line 11 after "{".I've attached a link to the code. Someone please help meI'm using better alchemy, ghost mode, and friendly stash. Link to comment Share on other sites More sharing options...
FrostDragon1557 Posted June 18, 2018 Share Posted June 18, 2018 Error [mod0000_mergedfiles]game\player\playerinput.ws(3476): Unexpected end of file found after '{' at line 9 Yeah i'm having the same problem but with line 9 and have no idea and have looked for a solution and can't seem to find one some help or a clue would be very helpful thanks Link to comment Share on other sites More sharing options...
SilentKILLeX Posted November 22, 2018 Share Posted November 22, 2018 have every one found a fix ? Link to comment Share on other sites More sharing options...
Recommended Posts