/// <summary>
    /// Calculate any possible critical hit/damage.
    /// </summary>
    /// <param name="Damage"></param>
    /// <param name="rollresult"></param>
    /// <returns></returns>
    private static bool RollForCritDamage(ref short Damage, Skills.SkillRollResult rollresult)
    {
        bool CriticalHit = false;

        if (rollresult == Skills.SkillRollResult.CriticalSuccess)
        {
            //based on dissasembly a crit is a 50:50 chance after the critical roll is scored

            //seems to be a 50:50 chance for a crit which gives double damage.
            //(48+(rng 0-30)) >>5
            int crit = (48 + Random.Range(0, 31) >> 5);
            Damage      = (short)(Damage * crit);
            CriticalHit = true;
        }

        return(CriticalHit);
    }
Esempio n. 2
0
    public override bool Eat()
    {
        int  FoodValue        = GameWorldController.instance.objDat.nutritionStats[item_id - 176].FoodValue;
        bool DrinkIsAlcoholic = false;
        int  StringNo;



        //uw1 strings
        //000~001~237~The water refreshes you. \n
        //000~001~238~You drink the port. \n
        //000~001~239~You drink the dark ale. \n

        //uw2 strings
        //000~001~252~The water refreshes you. \n
        //000~001~253~You drink the wine. \n
        //000~001~254~You drink the dark ale. \n

        switch (_RES)
        {
        case GAME_UW2:
            switch (item_id)
            {
            case 187:         //ale
                StringNo         = 254;
                DrinkIsAlcoholic = true;
                break;

            case 189:        //wine
                StringNo         = 253;
                DrinkIsAlcoholic = true;
                break;

            default:        //water
                StringNo = 252;
                break;
            }
            break;

        default:
            switch (item_id)
            {
            case 186:         //ale
                StringNo         = 239;
                DrinkIsAlcoholic = true;
                break;

            case 190:        //port
                StringNo         = 238;
                DrinkIsAlcoholic = true;
                break;

            default:        //water
                StringNo = 237;
                break;
            }
            break;
        }

        UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringNo));

        if (DrinkIsAlcoholic)
        {
            UWCharacter.Instance.Intoxication -= FoodValue;
            if (UWCharacter.Instance.Intoxication > 63)
            {
                UWCharacter.Instance.Intoxication = 63;
            }

            //Do a skill check for drunkeness vs strength.
            Skills.SkillRollResult result = Skills.SkillRoll(UWCharacter.Instance.PlayerSkills.STR, UWCharacter.Instance.Intoxication);
            switch (result)
            {
            case Skills.SkillRollResult.CriticalFailure:

                //clear intoxicaion.
                UWCharacter.Instance.Intoxication = 0;
                //Pass out drumk
                //000~001~256~As the alcohol hits you, you stumble and collapse into sleep. \n
                UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_as_the_alcohol_hits_you_you_stumble_and_collapse_into_sleep_));
                //sleep
                UWCharacter.Instance.Sleep();
                //wake up unstable
                UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_wake_feeling_somewhat_unstable_but_better_));
                break;

            case Skills.SkillRollResult.CriticalSuccess:
                //heal 2 points of health and you feel better.
                UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_the_drink_makes_you_feel_a_little_better_for_now_));

                UWCharacter.Instance.CurVIT = UWCharacter.Instance.CurVIT + 2;
                if (UWCharacter.Instance.CurVIT > UWCharacter.Instance.MaxVIT)
                {
                    UWCharacter.Instance.CurVIT = UWCharacter.Instance.MaxVIT;
                }
                break;

            default:
                //screen shake
                CameraShake.instance.ShakeCombat(0.5f);
                break;
            }
        }
        else
        {//water Healing effect. (water should be 1 point (-1 in table)
            FoodValue = Mathf.Abs(FoodValue);
            UWCharacter.Instance.CurVIT += FoodValue;
            if (UWCharacter.Instance.CurVIT > UWCharacter.Instance.MaxVIT)
            {
                UWCharacter.Instance.CurVIT = UWCharacter.Instance.MaxVIT;
            }
            //Clear intoxication as well.
            UWCharacter.Instance.Intoxication = 0;
        }
        if (_RES == GAME_UW2)
        {//Some food items leave left overs
            LeftOvers();
        }
        objInt().consumeObject();//destroy and remove from inventory/world.
        return(true);
    }
    /// <summary>
    /// NPC hits player
    /// </summary>
    /// <param name="playerUW">Player U.</param>
    /// <param name="npc">Npc.</param>
    public static void NPC_Hits_PC(UWCharacter playerUW, NPC npc)
    {
        int flankingbonus = 0;

        flankingbonus = CalcFlankingBonus(npc.objInt().heading, playerUW.currentHeading);
        int attackScore = npc.CurrentAttackScore + (npc.EquipDamage >> 1) + Random.Range(0, 5) + 7 + flankingbonus; //+Maybe Npc Level

        //Player defence
        //defence skill + sum of all armour+(skill with current weapon >>1) + unknownbonus(stored in critterdata)
        int DefenderScore = playerUW.PlayerSkills.GetSkill(Skills.SkillDefense) + playerUW.playerInventory.ArmourProtection;

        if (playerUW.PlayerCombat.currWeapon != null)
        {
            DefenderScore += (playerUW.PlayerSkills.GetSkill(playerUW.PlayerCombat.currWeapon.GetSkill()) >> 1);
        }
        else
        {
            DefenderScore += (playerUW.PlayerSkills.GetSkill(Skills.SkillUnarmed) >> 1);
        }

        Skills.SkillRollResult rollresult = Skills.SkillRoll(attackScore, DefenderScore);
        if ((_RES == GAME_UW1) && (npc.item_id == 124) && (rollresult == Skills.SkillRollResult.CriticalFailure || rollresult == Skills.SkillRollResult.Failure))
        {
            rollresult = Skills.SkillRollResult.Success;//Slasher of veils will always hit.
        }

        short Damage = 0;

        Damage = (short)(npc.CurrentAttackDamage + (npc.Strength / 5));
        Damage = (short)Mathf.Max(Damage, 2);
        int baseDamage = Damage;

        bool CriticalHit = RollForCritDamage(ref Damage, rollresult);

        // damage % 6 no of 1D6s to calculate the actual damage and then add the remainder as a final roll 1-remainder
        Damage = (short)(DamageRoll((short)(Damage / 6), 6) + DamageRoll(1, (short)(Damage % 6)));


        //TODO: damage for NPCS is scaled based on a lookup table and a property in their mobile data. This is similar to the player attack charge. (values stored in segment_60 in UW2 exe)
        //Lookup appears to be based on the value in the object at 0xF ( bits 12 to 15)
        //For now just scale it randomly
        Damage = (short)Random.Range(2, Damage + 1);

        switch (rollresult)
        {
        case Skills.SkillRollResult.CriticalSuccess:
        case Skills.SkillRollResult.Success:
        {
            Debug.Log("Base Damage = " + (short)(baseDamage) + " Final Damage = " + Damage);
            playerUW.ApplyDamage(Damage, npc.gameObject);

            //TODO: restore equipment damage and poisoning.

            //Ten more seconds of combat music
            MusicController.LastAttackCounter = 10.0f;
            if (ObjectInteraction.PlaySoundEffects)
            {
                UWCharacter.Instance.aud.clip = MusicController.instance.SoundEffects[MusicController.SOUND_EFFECT_MELEE_HIT_1];
                UWCharacter.Instance.aud.Play();
            }
            break;
        }

        case Skills.SkillRollResult.Failure:
        case Skills.SkillRollResult.CriticalFailure:
            //a miss.
            break;
        }


        ////////    int PlayerDefence = 0;
        ////////    if (playerUW.PlayerCombat.currWeapon != null)
        ////////    {
        ////////        PlayerDefence = playerUW.PlayerSkills.GetSkill(Skills.SkillDefense) + (playerUW.PlayerSkills.GetSkill(playerUW.PlayerCombat.currWeapon.GetSkill() + 1) / 2);
        ////////    }
        ////////    else
        ////////    {
        ////////        PlayerDefence = playerUW.PlayerSkills.GetSkill(Skills.SkillDefense) + (playerUW.PlayerSkills.GetSkill(Skills.SkillUnarmed) / 2);
        ////////    }
        ////////    int toHit = Mathf.Max(PlayerDefence - npc.Dexterity, 0);
        ////////    int roll = Random.Range(-1, 31);
        ////////    if ((_RES == GAME_UW1) && (npc.item_id == 124))
        ////////    {
        ////////        roll = 30;//Slasher will always hit.
        ////////    }
        ////////    int BaseDamage = npc.CurrentAttackDamage;//get the damage of the current attack
        ////////    if (((roll >= toHit) || (roll >= 30)) && (roll > -1))
        ////////    {
        ////////        int PlayerArmourScore = playerUW.playerInventory.getArmourScore();
        ////////        int ReducedDamage = Mathf.Max(1, BaseDamage - PlayerArmourScore);
        ////////        //Hit
        ////////        playerUW.ApplyDamage(Random.Range(1, ReducedDamage + 1), npc.gameObject);
        ////////        //reduce damage by protection
        ////////        if (BaseDamage > PlayerArmourScore)
        ////////        {
        ////////            //apply equipment damage to a random piece of armour
        ////////            playerUW.playerInventory.ApplyArmourDamage((short)Random.Range(0, npc.ArmourDamage + 1));
        ////////        }
        ////////        if (npc.PoisonLevel() > 0)
        ////////        {//roll for poisoning.
        ////////            if (!UWCharacter.Instance.isPoisonResistant())
        ////////            {//Player has resistence against poisoning
        ////////                int PoisonRoll = Random.Range(1, 30);
        ////////                if (PoisonRoll < npc.PoisonLevel())
        ////////                {
        ////////                    int PoisonToAdd = Random.Range(1, npc.PoisonLevel() + 1);
        ////////                    int newPlayPoison = (short)Mathf.Min(playerUW.play_poison + PoisonToAdd, 15);
        ////////                    UWCharacter.Instance.play_poison = (short)newPlayPoison;
        ////////                    if (UWCharacter.Instance.poison_timer == 0)
        ////////                    {
        ////////                        UWCharacter.Instance.poison_timer = 30f;
        ////////                    }
        ////////                }
        ////////            }

        ////////        }

        ////////        MusicController.LastAttackCounter = 10.0f; //Ten more seconds of combat music
        ////////        if (ObjectInteraction.PlaySoundEffects)
        ////////        {
        ////////            UWCharacter.Instance.aud.clip = MusicController.instance.SoundEffects[MusicController.SOUND_EFFECT_MELEE_HIT_1];
        ////////            UWCharacter.Instance.aud.Play();
        ////////        }
        ////////    }
    }
    /// <summary>
    /// Combat calculations for PC hitting an NPC
    /// </summary>
    /// <param name="playerUW">Player Character</param>
    /// <param name="npc">Npc.</param>
    /// <param name="hit">Hit.</param>
    public static void PC_Hits_NPC(UWCharacter playerUW, WeaponMelee currentWeapon, string StrikeName, float StrikeCharge, NPC npc, RaycastHit hit)
    {
        int attackScore = 0;

        int   flankingbonus = 0; //need to calcu but depending on relative headings between attacker and defender.
        int   magicbonus    = 0; //currently unknown what provides this but is calculated by casting/5 + 0xA when set.
        short MinCharge;
        short MaxCharge;

        if (npc != null)
        {
            //recalc position to get the correct heading for the flanking bonus
            npc.objInt().UpdatePosition();
            flankingbonus = CalcFlankingBonus(playerUW.currentHeading, npc.objInt().heading);
        }


        if (currentWeapon != null)
        {
            attackScore = (playerUW.PlayerSkills.GetSkill(Skills.SkillAttack) >> 1) + playerUW.PlayerSkills.GetSkill(currentWeapon.GetSkill()) + (playerUW.PlayerSkills.DEX / 7) + magicbonus + flankingbonus;
            if (GameWorldController.instance.difficulty == 0)
            {//bonus of 7 for easy difficulty
                attackScore += 7;
            }
            attackScore += currentWeapon.AccuracyBonus();//Given by the accuracy enchantments. Note in vanilla UW2 accuracy actually increases damage and not attack score. This is fixed here.

            MinCharge = currentWeapon.GetMinCharge();
            MaxCharge = currentWeapon.GetMaxCharge();
        }
        else
        {
            //use the unarmed calculations
            attackScore = (playerUW.PlayerSkills.GetSkill(Skills.SkillAttack) >> 1) + playerUW.PlayerSkills.GetSkill(Skills.SkillUnarmed) + (playerUW.PlayerSkills.DEX / 7) + magicbonus + flankingbonus;
            if (GameWorldController.instance.difficulty == 0)
            {//bonus of 7 for easy difficulty
                attackScore += 7;
            }
            MinCharge = WeaponMelee.GetMeleeMinCharge();
            MaxCharge = WeaponMelee.GetMeleeMaxCharge();
        }


        //Get base damage
        int BaseSwingDamage   = GetPlayerBaseDamage(currentWeapon, StrikeName);
        int basePower         = (short)(GameWorldController.instance.objDat.critterStats[63].Strength / 9); //the player is actually a critter so power in this case is their STR.
        int WeaponBonusDamage = 0;

        if (currentWeapon != null)
        {
            WeaponBonusDamage = currentWeapon.DamageBonus();
        }
        else
        {                                                                                            //unarmed
            basePower  = (short)(GameWorldController.instance.objDat.critterStats[63].Strength / 6); //the player is actually a critter so power in this case is their STR.
            basePower += (playerUW.PlayerSkills.GetSkill(Skills.SkillUnarmed) / 5);
        }


        //scale base damage by charge. Min damage is always 2.
        short Damage = (short)(basePower + BaseSwingDamage + WeaponBonusDamage);

        // damage % 6 no of 1D6s to calculate the actual damage and then add the remainder as a final roll 1-remainder
        Damage = (short)(DamageRoll((short)(Damage / 6), 6) + DamageRoll(1, (short)(Damage % 6)));

        //Damage is scaled by the amount of weapon charge built up.
        Damage = CalcAttackChargeDamage((short)StrikeCharge, MinCharge, MaxCharge, Damage);

        //And a flat flanking bonus
        Damage += (short)flankingbonus;

        //Min damage will be 2.
        Damage = (short)(Mathf.Max(Damage, 2));

        Skills.SkillRollResult rollresult = Skills.SkillRoll(attackScore, npc.Defence());

        bool CriticalHit = RollForCritDamage(ref Damage, rollresult);

        switch (rollresult)
        {
        case Skills.SkillRollResult.CriticalSuccess:
        case Skills.SkillRollResult.Success:
        {
            Debug.Log("Base Damage = " + ((short)(basePower + BaseSwingDamage + WeaponBonusDamage)) + " Final Damage = " + Damage);
            if (CriticalHit)
            {
                Impact.SpawnHitImpact(Impact.ImpactBlood(), npc.GetImpactPoint() + Vector3.up * 0.1f, npc.objInt().GetHitFrameStart(), npc.objInt().GetHitFrameEnd());
            }
            npc.ApplyAttack(Damage, playerUW.gameObject);
            Impact.SpawnHitImpact(Impact.ImpactBlood(), npc.GetImpactPoint(), npc.objInt().GetHitFrameStart(), npc.objInt().GetHitFrameEnd());
            if (currentWeapon != null)
            {        ///Performs the onHit action of the melee weapon.
                currentWeapon.onHit(hit.transform.gameObject);
            }
            break;
        }

        case Skills.SkillRollResult.Failure:
            npc.ApplyAttack(0, playerUW.gameObject);
            npc.npc_aud.PlayCombatMissed();
            break;

        case Skills.SkillRollResult.CriticalFailure:
        {
            npc.ApplyAttack(0, playerUW.gameObject);
            npc.npc_aud.PlayCombatMissed();
            //Damage weapon
            short durability = currentWeapon.getDurability();
            if (durability <= 30)
            {
                currentWeapon.SelfDamage((short)Mathf.Max(0, Random.Range(0, npc.EquipDamage + 1) - durability));
            }
            break;
        }
        }
    }
Esempio n. 5
0
    public override bool ActivateByObject(ObjectInteraction ObjectUsed)
    {    //Code for handling otherobjects used on this object
         //Doors can be used by keys, picks and spikes.
        //ObjectInteraction objIntUsed = ObjectUsed.GetComponent<ObjectInteraction>();
        if (ObjectUsed != null)
        {
            switch (ObjectUsed.GetItemType())
            {
            case ObjectInteraction.KEY:                     //Key
                DoorKey dk = ObjectUsed.GetComponent <DoorKey>();
                if (dk != null)
                {
                    if (state() == true)
                    {
                        //Door is already open
                        UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 6));
                        return(true);
                    }
                    ObjectInteraction doorlock = getLockObjInt();
                    if (doorlock == null)
                    {
                        UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 3));
                        return(false);
                    }
                    if ((doorlock.link & 0x3F) == dk.owner)                         //This is a valid key for the door.
                    {
                        ToggleLock(true);
                        if (locked() == true)
                        {                                        //Locked message
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 4));
                        }
                        else
                        {                                        //Unlockedmessage
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 5));
                        }
                        return(true);
                    }
                    else
                    {
                        if (link == 53)
                        {                                //There is no lock
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 3));
                        }
                        else
                        {                                //That is the wrong key.
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 2));
                        }
                        return(true);
                    }
                }
                break;

            case ObjectInteraction.LOCKPICK:                            //lockpick
            {
                //lock pick skill check is based on the zpos of the "lock" object * 3 vs the players (lockpick skill + 1)
                //Locks cannot be picked if the zpos is 0xE or greater. In either case the skillcheck is attempted.
                ObjectInteraction LockObject = getLockObjInt();
                if (LockObject != null)
                {
                    int skillvalue  = UWCharacter.Instance.PlayerSkills.PickLock + 1;
                    int targetvalue = LockObject.zpos * 3;
                    Skills.SkillRollResult skillroll = Skills.SkillRoll(skillvalue, targetvalue);

                    if (LockObject.zpos >= 0xE)
                    {        //unpickable
                        if (skillroll == Skills.SkillRollResult.CriticalFailure)
                        {
                            BreakLockPick(ObjectUsed);
                        }
                        else
                        {
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_your_lockpicking_attempt_failed_));
                        }
                    }
                    else
                    {
                        switch (skillroll)
                        {
                        case Skills.SkillRollResult.CriticalFailure:
                        {
                            BreakLockPick(ObjectUsed);
                            break;
                        }

                        case Skills.SkillRollResult.Failure:
                        {
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_your_lockpicking_attempt_failed_));
                            break;
                        }

                        case Skills.SkillRollResult.Success:
                        case Skills.SkillRollResult.CriticalSuccess:
                        {
                            UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_succeed_in_picking_the_lock_));
                            UnlockDoor(true);
                            break;
                        }
                        }
                    }
                }
                else
                {
                    UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, 3));        //There is no lock on that.
                }
            }
            break;

            //{
            //if (Pickable==true)
            //	{
            //		if (UWCharacter.Instance.PlayerSkills.TrySkill(Skills.SkillPicklock, Skills.DiceRoll(1,25)))
            //		{
            //		UWHUD.instance.MessageScroll.Add (StringController.instance.GetString (1,StringController.str_you_succeed_in_picking_the_lock_));
            //		UnlockDoor(true);
            //		}
            //	else
            //		{
            //		//Debug.Log ("Picklock failed!");
            //		UWHUD.instance.MessageScroll.Add (StringController.instance.GetString (1,StringController.str_your_lockpicking_attempt_failed_));
            //		//objIntUsed.consumeObject();
            //		}
            //	}
            //else
            //	{
            //		UWHUD.instance.MessageScroll.Add (StringController.instance.GetString (1,StringController.str_your_lockpicking_attempt_failed_));
            //	}
            //break;
            //}
            case ObjectInteraction.SPIKE:
            {
                if (Spike())
                {
                    ObjectUsed.consumeObject();
                }
                break;
            }

            default:
                return(false);
            }
        }
        else
        {
            return(false);
        }
        return(true);
    }
    /// <summary>
    /// Event handler for processing the repair question y/n
    /// </summary>
    /// <param name="ans">Ans.</param>
    public void OnSubmitPickup(string ans)
    {
        Time.timeScale = 1.0f;
        UWHUD.instance.InputControl.gameObject.SetActive(false);
        WindowDetectUW.WaitingForInput = false;
        UWHUD.instance.MessageScroll.Clear();//="";
        if (ans.Substring(0, 1).ToUpper() == "Y")
        {
            //do the repair
            //Play the cutscene.
            switch (_RES)
            {
            case GAME_UW2:
                //todo
                break;

            default:
                UWHUD.instance.CutScenesSmall.anim.SetAnimation = "cs404.n01";
                break;
            }

            int RepairDifficulty = repairEstimate();

            Skills.SkillRollResult result = Skills.SkillRoll(UWCharacter.Instance.PlayerSkills.Repair, RepairDifficulty);

            switch (result)
            {
            case Skills.SkillRollResult.CriticalFailure:    //attempt fails. dice roll of 0-63. If repair skill is lower than result damage item by another roll (0-7)+4;
            {
                if (Random.Range(0, 64) >= UWCharacter.Instance.PlayerSkills.Repair)
                {
                    int damage = Random.Range(0, 7) + 4;
                    quality = (short)(quality - (short)damage);
                    if (quality > 0)
                    {
                        UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_damaged_the_) + StringController.instance.GetObjectNounUW(item_id));
                    }
                }
            }
            break;

            case Skills.SkillRollResult.Failure:    //attempt fails. no change to item.
                UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_your_attempt_has_no_effect_on_the_) + StringController.instance.GetObjectNounUW(item_id));
                break;

            case Skills.SkillRollResult.Success:    //repair up to (repair skill/5+3)
                int newQuality = (UWCharacter.Instance.PlayerSkills.Repair / 5 + 3);
                if (quality >= newQuality)
                {
                    UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_your_attempt_has_no_effect_on_the_) + StringController.instance.GetObjectNounUW(item_id));
                }
                else
                {
                    quality = (short)newQuality;
                    if (quality > 63)
                    {
                        UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_have_fully_repaired_the_) + StringController.instance.GetObjectNounUW(item_id));
                        quality = 63;
                    }
                    else
                    {
                        UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_have_partially_repaired_the_) + StringController.instance.GetObjectNounUW(item_id));
                    }
                }


                break;

            case Skills.SkillRollResult.CriticalSuccess:    //fully repair the item.
                quality = 63;
                UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_have_fully_repaired_the_) + StringController.instance.GetObjectNounUW(item_id));
                break;
            }


            if (quality <= 0)
            {
                //destroy the item.
                UWHUD.instance.MessageScroll.Add(StringController.instance.GetString(1, StringController.str_you_destroyed_the_) + StringController.instance.GetObjectNounUW(item_id));
                objInt().consumeObject();//ToDO: Create DEBRIS
            }
            else
            {
                UpdateQuality();
            }
        }
        //cancel the repair
        CurrentObjectInHand = null;
    }