コード例 #1
0
        public void ProcessDarkKnightDarkForce(int maxHp)
        {
            var pSkill = Parent.Skills.Get((int)Skills.DARKKNIGHT_DARK_FORCE);

            if (pSkill != null)
            {
                var minAmount = pSkill.X_Effect * 0.01 * maxHp;                 // x is low end of range
                var maxAmount = pSkill.Y_Effect * 0.01 * maxHp;                 // y is high end of range

                //Parent.SendMessage($"Min: {minAmount} | Max: {maxAmount}");

                var effect = new UserEffectPacket(UserEffect.SkillAffected)
                {
                    nSkillID = pSkill.nSkillID,
                };

                if (Parent.Stats.nHP > minAmount && Parent.Stats.nHP < maxAmount)                 // in range
                {
                    if (!bDarkForce)
                    {
                        effect.bDarkForceActive = true;
                        effect.BroadcastEffect(Parent);
                    }
                }
                else                 // not in range
                {
                    if (bDarkForce)
                    {
                        effect.bDarkForceActive = true;
                        effect.BroadcastEffect(Parent);
                    }
                }
            }
        }
コード例 #2
0
        private void DoDice(int nSkillID, byte nSLV)
        {
            Parent.Buffs.Remove(nSkillID);

            var newBuff = new BuffSkill(nSkillID, nSLV);

            newBuff.State = (byte)(Constants.Rand.Next(6) + 1);

            var effect = new UserEffectPacket(UserEffect.SkillAffectedSelect)
            {
                nSelect  = (byte)newBuff.State,
                nSkillID = nSkillID,
                nSLV     = nSLV
            };

            effect.BroadcastEffect(Parent);

            if (newBuff.State <= 1)
            {
                return;
            }

            newBuff.GenerateDice();

            Parent.Buffs.Add(newBuff);
        }
コード例 #3
0
        private void DoTimeleap(int nSkillID)
        {
            if (Parent.Party?.Count > 1)
            {
                Parent.Party.ForEachMemberInField(Parent.Field.dwUniqueId, c => execute(c));
            }
            else
            {
                execute(Parent);
            }

            void execute(Character c)
            {
                var effect = new UserEffectPacket(UserEffect.SkillAffected)
                {
                    nSkillID = nSkillID,
                };

                effect.BroadcastEffect(c);

                foreach (var cd in new List <Cooldown>(c.Cooldowns))
                {
                    if (cd.nSkillID != (int)Skills.VIPER_TIME_LEAP)
                    {
                        Parent.Cooldowns.Remove(cd);
                    }
                }
            }
        }
コード例 #4
0
        public void CheckDragonFury(int maxMp)         // CWvsContext::CheckDragonFury
        {
            if (Parent.Skills.Get((int)Skills.EVAN_DRAGON_FURY) is SkillEntry pSkill)
            {
                var minAmount = pSkill.X_Effect * maxMp / 100;                 // x is low end of range
                var maxAmount = pSkill.Y_Effect * maxMp / 100;                 // y is high end of range

                var effect = new UserEffectPacket(UserEffect.SkillAffected)
                {
                    nSkillID = pSkill.nSkillID,
                };

                if (Parent.Stats.nMP > minAmount && Parent.Stats.nMP < maxAmount)                 // in range
                {
                    if (nDragonFury == 0)
                    {
                        effect.bDragonFuryActive = true;
                        effect.BroadcastEffect(Parent);
                        nDragonFury = pSkill.Template.Damage(pSkill.nSLV);
                    }
                }
                else                 // not in range
                {
                    if (nDragonFury != 0)
                    {
                        effect.bDragonFuryActive = false;
                        effect.BroadcastEffect(Parent);
                    }
                }
            }
        }
コード例 #5
0
        public bool Update()
        {
            switch (nType)
            {
            case AffectedAreaType.UserSkill:
                foreach (var mob in Field.Mobs)
                {
                    if (!rcArea.PointInRect(mob.Position.CurrentXY))
                    {
                        continue;
                    }

                    mob.TryApplySkillDamageStatus
                        (Field.Users[dwOwnerId], nSkillID, nSLV, 0);
                }
                break;

            case AffectedAreaType.BlessedMist:                     // TODO fix the recovery numbers, its incorrect rn
            {
                var rate = MasterManager.SkillTemplates[nSkillID].X(nSLV) * 0.01;
                foreach (var user in Field.Users)
                {
                    if (!rcArea.PointInRect(user.Position.CurrentXY))
                    {
                        continue;
                    }

                    user.Modify.Heal(0, (int)(user.BasicStats.nMMP * rate));

                    var effect = new UserEffectPacket(UserEffect.SkillAffected)
                    {
                        nSkillID = nSkillID,
                        nSLV     = nSLV,
                    };

                    effect.BroadcastEffect(user);
                }
            }
            break;

            case AffectedAreaType.MobSkill:
                foreach (var user in Field.Users)
                {
                    if (!rcArea.PointInRect(user.Position.CurrentXY))
                    {
                        continue;
                    }

                    var toAdd = new Debuff(nSkillID, nSLV);
                    toAdd.StatType = SecondaryStatFlag.Poison;
                    toAdd.Generate();
                    user.Buffs.Remove(toAdd.nBuffID);
                    user.Buffs.Add(toAdd);
                }
                break;
            }

            return(StartTime.MillisSinceStart() >= Duration);
        }
コード例 #6
0
        public void AddSkillBuff(int nSkillID, int nSLV, double durationMultiplier = 1.0, int nOption = 0)
        {
            if (nSkillID == (int)Skills.MECHANIC_SAFETY)
            {
                nOption = Parent.Stats.SecondaryStats.rBeholder;
            }

            if (GetOrDefault(nSkillID) is BuffSkill bs)
            {
                if (bs.nSLV < nSLV)
                {
                    bs.nSLV = (byte)nSLV;
                }

                bs.State = nOption;

                UpdateBuffInfo(bs);
            }
            else
            {
                var newBuff = new BuffSkill(nSkillID, (byte)nSLV);

                if (newBuff.Template.Morph > 0)
                {
                    newBuff.State = Parent.Stats.nGender;                     // haxed
                }

                newBuff.Generate(durationMultiplier);

                if (newBuff.StatType != SecondaryStatFlag.None_DONT_USE)                 // TODO phase this out
                {
                    RemoveIf(b => b.StatType == newBuff.StatType);
                }

                if (newBuff.Template.HasAffected)
                {
                    var effect = new UserEffectPacket(UserEffect.SkillAffected)
                    {
                        nSkillID = nSkillID,
                    };

                    effect.BroadcastEffect(Parent);
                }

                newBuff.State = nOption;

                Add(newBuff);
            }
        }
コード例 #7
0
        private void SwallowMob(int dwSwallowMobId, byte nSLV)
        {
            if (Parent.Field.Mobs.Remove(dwSwallowMobId))
            {
                var effect = new UserEffectPacket(UserEffect.SkillUse)
                {
                    nSkillID = (int)Skills.WILDHUNTER_SWALLOW,
                    nSLV     = nSLV,
                };

                effect.BroadcastEffect(Parent);

                Parent.Cooldowns.UpdateOrInsert((int)Skills.WILDHUNTER_SWALLOW, 30);
            }
        }
コード例 #8
0
        private void DoPartyHeal(int nSkillID, int nHP)         //  // BMS: 0x005D3295
        {
            var nIntFactor   = Parent.BasicStats.nINT * 0.8;
            var nIntModifier = nIntFactor + Constants.Rand.Next() % (Parent.BasicStats.nINT - nIntFactor);

            // TODO determine if we want to even bother with adding the MAD factor or just increase the int/luk factors
            //var nMad = sender.Buffs.Sum(buff => buff.Stat[SecondaryStatFlags.MAD] != null ? buff.Stat[SecondaryStatFlags.MAD].nValue : 0);
            //var nMadFactor = nMad + nMad; // addition faster than multiplication :kek:
            var nHeal         = (nIntModifier * 1.5 + Parent.BasicStats.nLUK);    // * 0.01; // nMadFactor * 0.01;
            var nMembersInMap = Parent.Party != null?Parent.Party.MembersInMap(Parent.Field.dwUniqueId) : 1;

            var nHealAmount = (int)(nHeal * (nMembersInMap * 0.3 + 1.0) * nHP * 0.01 / nMembersInMap);

            if (Parent.Party?.Count > 1)
            {
                var effect = new UserEffectPacket(UserEffect.SkillAffected)
                {
                    nSkillID = nSkillID,
                };

                var nExp = 0;

                Parent.Party.ForEachMemberInField(Parent.Field.dwUniqueId, member =>
                {
                    if (member.Stats.nHP > 0)
                    {
                        var nPrevHP = member.Stats.nHP;
                        member.Modify.Heal(nHealAmount);

                        if (member.dwId != Parent.dwId)
                        {
                            nExp += 20 * (member.Stats.nHP - nPrevHP) / (8 * member.Stats.nLevel + 190);
                            effect.BroadcastEffect(member);
                        }
                    }
                });

                if (nExp > 0)
                {
                    Parent.Modify.GainExp(nExp);
                }
            }
            else
            {
                Parent.Modify.Heal(nHealAmount);
            }
        }
コード例 #9
0
        public void CompleteQuest()
        {
            var Parent = Script.Parent.Character;

            Quest.nState     = QuestActType.QuestComplete;
            Quest.tCompleted = DateTime.Now;

            var effect = new UserEffectPacket(UserEffect.QuestComplete);

            effect.BroadcastEffect(Parent);

            Parent.SendPacket(CPacket.CQuestMan.QuestCompleted(Quest.nQuestID));

            Parent.SendPacket(CPacket.CQuestMan
                              .QuestRecordMessage(Quest));

            Parent.SendPacket(CPacket.CQuestMan
                              .UserQuestResult(QuestResultType.Success, Quest, Quest.Template.EndNPC));
        }
コード例 #10
0
        /// <summary>
        /// Updates and sends a TemporaryStatSet packet to parent and remote client around parent
        /// This informs the client of changes to the buff without the overhead of removing the buff and re-adding it
        /// </summary>
        /// <param name="toUpdate"></param>
        public void UpdateBuffInfo(AbstractBuff toUpdate)
        {
            toUpdate.Stat.Clear();
            toUpdate.Generate();

            // no need to remove first cuz it will overwrite the previous value
            Parent.Stats.SecondaryStats.SetFromSecondaryStat(Parent, toUpdate.Stat);

            toUpdate.Stat.BroadcastSet(Parent);

            Parent.ValidateStat();

            if (toUpdate is BuffSkill buff && buff.Template.HasAffected)
            {
                var effect = new UserEffectPacket(UserEffect.SkillAffected)
                {
                    nSkillID = buff.nSkillID,
                };

                effect.BroadcastEffect(Parent);
            }
        }
コード例 #11
0
        public static void Handle(int nSkillID, byte nSLV, Character c, CInPacket p)
        {
            var ldwTeslaCoilSummonedID = new int[2];

            if (nSkillID == (int)Skills.MECHANIC_TESLA_COIL)
            {
                var nDistance = p.Decode1();

                if (nDistance == 2)
                {
                    ldwTeslaCoilSummonedID[0] = p.Decode4();
                    ldwTeslaCoilSummonedID[1] = p.Decode4();
                }
            }

            var x = p.Decode2();
            var y = p.Decode2();

            var bLeft = p.Decode1() > 0;

            var unk = p.Decode1();             // FH?

            if (nSkillID == (int)Skills.WILDHUNTER_MINE_DUMMY_SUMMONED && !c.Buffs.Contains((int)Skills.WILDHUNTER_MINE))
            {
                c.SendMessage("Unable to spawn mine when buff isn't activated.");
                return;
            }

            if (!c.Skills.Cast(nSkillID, bLeft, true))
            {
                return;
            }

            var robotMastery       = c.Skills.Get((int)Skills.MECHANIC_MASTERY);
            var durationMultiplier = (100 + (robotMastery?.X_Effect ?? 0)) * 0.01;

            var pSkill = c.Skills.Get(nSkillID, true);

            if (ldwTeslaCoilSummonedID[0] > 0)
            {
                if (!c.Field.Summons.Handle_TeslaCoil(c, nSLV, x, y, ldwTeslaCoilSummonedID))
                {
                    return;
                }
            }
            else
            {
                var summon = c.Field.Summons.CreateSummon(c, nSkillID, nSLV, x, y);

                switch (summon.nMoveAbility)
                {
                case SummonMoveAbility.CircleFollow:
                case SummonMoveAbility.Follow:
                    c.Buffs.AddSkillBuff(nSkillID, pSkill.nSLV, durationMultiplier);
                    break;
                }
            }

            var effect = new UserEffectPacket(UserEffect.SkillUse)
            {
                nSkillID = nSkillID,
                nSLV     = pSkill.nSLV,
            };

            effect.BroadcastEffect(c, false);

            switch ((Skills)nSkillID)
            {
            case Skills.MECHANIC_VELOCITY_CONTROLER:
            {
                foreach (var item in c.Field.Mobs)
                {
                    item.TryApplySkillDamageStatus(c, nSkillID, pSkill.nSLV, 0);
                }

                c.Field.nVelocityControllerdwId = c.dwId;
                break;
            }

            case Skills.MECHANIC_AR_01:
                c.Skills.CastAffectedAreaSkill(nSkillID, nSLV, (short)pSkill.BuffTime,
                                               c.Position.CurrentXY, pSkill.Template.LT, pSkill.Template.RB);
                //if (c.Party?.Count > 1)
                //{
                // c.Party.ApplyBuffToParty(c, c.Field.dwUniqueId, nSkillID, nSLV);
                //}
                //else
                //{
                // c.Buffs.AddSkillBuff(nSkillID, pSkill.nSLV);
                //}
                break;
            }
        }
コード例 #12
0
        public void Stats(Action <StatModifier> action, bool bExclRequest = true)
        {
            var ctx = new StatModifier(Parent);

            action?.Invoke(ctx);

            if ((ctx.Flag & ModifyStatFlags.EXP) > 0)
            {
                if (ctx.EXP < 0)
                {
                    ctx.EXP = 0;
                }

                var nExpSurplus = ctx.EXP - NextLevel.get_next_level_exp(ctx.Level - 1);

                // make sure this is before levelup func
                var levels    = 0;
                var jobLevels = 0;

                int beforesp = ctx.SP;

                while (nExpSurplus >= 0)                 // while has more exp than required to reach next level
                {
                    ctx.EXP = nExpSurplus;

                    if (!ctx.try_process_levelup())
                    {
                        break;
                    }

                    nExpSurplus = ctx.EXP - NextLevel.get_next_level_exp(ctx.Level - 1);
                    levels     += 1;

                    Parent.NotifySocialChannels(SocialNotiflag.ChangeLevel);

                    var job = ctx.Job;
                    ctx.AutoJobAdvanceEvent(Parent);
                    if (job != ctx.Job)
                    {
                        jobLevels += 1;
                    }
                }

                if (levels > 0)
                {
                    if (ctx.HP > 0)
                    {
                        ctx.HP = Parent.BasicStats.nMHP;
                        ctx.MP = Parent.BasicStats.nMMP;
                    }

                    var effect = new UserEffectPacket(UserEffect.LevelUp);
                    effect.BroadcastEffect(Parent);

                    ctx.SP += (short)(jobLevels * 1);

                    var aftersp = ctx.SP - beforesp;

                    Parent.SendPacket(CPacket.IncSPMessage((byte)aftersp, ctx.Job));                     // send sp gain message
                    Parent.ValidateStat();
                }
            }

            if ((ctx.Flag & ModifyStatFlags.Money) != 0)
            {
                ctx.Money = Math.Max(0, ctx.Money);
            }

            if ((ctx.Flag & ModifyStatFlags.POP) != 0)
            {
                ctx.POP = Math.Max((short)0, ctx.POP);
            }

            if ((ctx.Flag & ModifyStatFlags.Job) != 0)
            {
                Parent.Skills.SetMasterLevels();

                var effect = new UserEffectPacket(UserEffect.JobChanged);
                effect.BroadcastEffect(Parent);

                if (JobLogic.IsEvan(ctx.Job))
                {
                    if (ctx.Job == 2200 && Parent.Dragon is null)
                    {
                        Parent.Dragon = new CDragon(Parent);
                        Parent.Quests.OnCompleteQuest(null, 22100, 0, true);
                    }

                    Parent.Dragon.SpawnDragonToMap();                     // update visuals
                }
                else
                {
                    Parent.Modify.Skills(mod =>
                    {
                        switch (ctx.Job)
                        {
                        // hacking aran skills together for now. TODO add a ForceVisible field or something to the skill class
                        case 2100:
                            mod.AddEntry(21000000, entry => entry.CurMastery = entry.MaxLevel);
                            mod.AddEntry(21001003, entry => entry.CurMastery = entry.MaxLevel);
                            break;

                        case 2110:
                            mod.AddEntry(21100000, entry => entry.CurMastery = entry.MaxLevel);
                            mod.AddEntry(21100002, entry => entry.CurMastery = entry.MaxLevel);
                            mod.AddEntry(21100004, entry => entry.CurMastery = entry.MaxLevel);
                            mod.AddEntry(21100005, entry => entry.CurMastery = entry.MaxLevel);
                            break;

                        case 2111:
                            mod.AddEntry(21110002, entry => entry.CurMastery = entry.MaxLevel);
                            break;

                        case 3300:
                            mod.AddEntry(30001061, entry => entry.nSLV = 1);
                            mod.AddEntry(30001062, entry => entry.nSLV = 1);
                            break;

                        case 3500:
                            mod.AddEntry(30001068, entry => entry.nSLV = 1);
                            break;
                        }

                        foreach (var skill in MasterManager.SkillTemplates.GetJobSkills(ctx.Job))
                        {
                            var template = MasterManager.SkillTemplates[skill];

                            if (template.MasterLevel > 0)
                            {
                                mod.AddEntry(skill, entry => entry.CurMastery = (byte)template.MasterLevel);
                            }
                        }
                    });
                }

                // notify correct channels
                Parent.NotifySocialChannels(SocialNotiflag.ChangeJob);
            }

            if ((ctx.Flag & ModifyStatFlags.HP) > 0 || (ctx.Flag & ModifyStatFlags.MaxHP) > 0)
            {
                if (ctx.HP <= 0)                 // TODO move death exp loss (and safety charm) handling here
                {
                    Parent.Field.Summons.RemoveCharSummons(Parent.dwId, SummonLeaveType.LEAVE_TYPE_USER_DEAD);
                }

                if (ctx.Job == 132)                 // dark knight
                {
                    Parent.Skills.ProcessDarkKnightDarkForce(Parent.BasicStats.nMHP);
                }
            }

            if (((ctx.Flag & ModifyStatFlags.MP) > 0 || (ctx.Flag & ModifyStatFlags.MaxMP) > 0) && ctx.Job >= 2216 && ctx.Job <= 2218)             // evan
            {
                Parent.Skills.CheckDragonFury(Parent.BasicStats.nMMP);
            }

            if ((ctx.Flag & ModifyStatFlags.BasicStat) != 0)
            {
                Parent.ValidateStat();
            }

            if (ctx.Flag > 0)
            {
                Parent.SendPacket(CPacket.StatChanged(ctx, bExclRequest));
            }
        }
コード例 #13
0
        public static void Handle_SummonedSkill(WvsGameClient c, CInPacket p)
        {
            var dwSummonedID = p.Decode4();
            var item         = c.Character.Field.Summons[dwSummonedID];

            if (item is null)
            {
                return;
            }

            var nBuffSkillID = p.Decode4();

            var pSkill = item.Parent.Skills.Get(nBuffSkillID, true);

            if (pSkill is null)
            {
                item.Parent.SendMessage($"Unable to find Skill ID {nBuffSkillID}.");
                return;
            }

            var nAction = p.Decode1();

            var nIntervalMillis = SkillLogic.get_summoned_attack_delay(pSkill.nSkillID, pSkill.nSLV, (int)pSkill.X_Effect);

#if DEBUG
            item.Parent.SendMessage("Skill ID sent from summon: " + nBuffSkillID);
#endif

            if (!item.tLastBuffTime.AddedMillisExpired(nIntervalMillis))
            {
                return;
            }

            item.tLastBuffTime = DateTime.Now;

            switch ((Skills)nBuffSkillID)
            {
            case Skills.MECHANIC_HEALING_ROBOT_H_LX:
            {
                if (item.Parent.Party != null)
                {
                    item.Parent.Party.ApplyBuffToParty(item.Parent, item.Field.dwUniqueId, nBuffSkillID, pSkill.nSLV);
                }
                else if (item.Parent.Stats.nHP > 0)
                {
                    var nHealAmount = (int)(item.Parent.BasicStats.nMHP * pSkill.Template.HP(pSkill.nSLV) * 0.01);

                    item.Parent.Modify.Heal(nHealAmount);
                }
            }
            break;

            case Skills.DARKKNIGHT_BEHOLDERS_HEALING:
            {
                if (item.Parent.Stats.nHP > 0)
                {
                    var nHealAmount = pSkill.Template.HP(pSkill.nSLV);
                    item.Parent.Modify.Heal(nHealAmount);
                }
            }
            break;

            case Skills.DARKKNIGHT_BEHOLDERS_BUFF:
            {
                if (item.Parent.Stats.nHP > 0)
                {
                    var nType = p.Decode1();

                    var buffid = 2022125 + Constants.Rand.Next(0, 5);

                    if (!item.Parent.Buffs.Contains(-buffid))
                    {
                        var buff = new BuffConsume(buffid);
                        buff.GenerateBeholderBuff(item.Parent);

                        item.Parent.Buffs.Add(buff);
                    }
                }
            }
            break;

            case Skills.MECHANIC_ROBOROBO:
            {
                item.Field.Summons.CreateSummon(item.Parent, (int)Skills.MECHANIC_ROBOROBO_DUMMY,
                                                item.nSLV,
                                                item.Position.X,
                                                item.Position.Y);
            }
            break;

            default:
                item.Parent.SendMessage("Unhandled summon skill ID: " + nBuffSkillID);
                return;
            }

            var effect = new UserEffectPacket(UserEffect.SkillAffected)
            {
                nSkillID = nBuffSkillID,
                nSLV     = pSkill.nSLV,
            };

            effect.BroadcastEffect(item.Parent);                                                                  // i think this includes parent

            item.Field.Broadcast(CPacket.CSummonedPool.SummonedSkill(item, item.nSkillID, nAction), item.Parent); // i think this excludes parent
        }