Пример #1
0
        private static bool LoadAttribute(int powerSNO, GameAttributeMap attributes, int attributeId, out float result)
        {
            GameAttribute attr      = GameAttribute.Attributes[attributeId];
            bool          needs_key = _powerKeyedAttributes.Contains(attributeId);

            if (attr is GameAttributeF)
            {
                if (needs_key)
                {
                    result = attributes[(GameAttributeF)attr, powerSNO];
                }
                else
                {
                    result = attributes[(GameAttributeF)attr];
                }

                return(true);
            }
            else if (attr is GameAttributeI)
            {
                if (needs_key)
                {
                    result = (float)attributes[(GameAttributeI)attr, powerSNO];
                }
                else
                {
                    result = (float)attributes[(GameAttributeI)attr];
                }

                return(true);
            }
            else if (attr is GameAttributeB)
            {
                if (needs_key)
                {
                    result = attributes[(GameAttributeB)attr, powerSNO] ? 1 : 0;
                }
                else
                {
                    result = attributes[(GameAttributeB)attr] ? 1 : 0;
                }

                return(true);
            }
            else
            {
                Logger.Error("invalid attribute {0}", attributeId);
                result = 0;
                return(false);
            }
        }
Пример #2
0
        private static bool LoadIdentifier(int powerSNO, TagKeyScript scriptTag, GameAttributeMap attributes, Random rand,
                                           int numb1, int numb2, int numb3, int numb4,
                                           out float result)
        {
            switch (numb1)
            {
            case 0:
                return(LoadAttribute(powerSNO, attributes, numb2, out result));

            case 1:     // slevel
                result = attributes[GameAttribute.Skill, powerSNO];
                return(true);

            case 22:     // absolute power formula ref
                return(Evaluate(numb2, new TagKeyScript(numb3), attributes, rand, out result));

            default:
                if (numb1 >= 23 && numb1 <= 62)     // SF_N, relative power formula ref
                {
                    int          SF_N        = numb1 - 23;
                    TagKeyScript relativeTag = PowerTagHelper.GenerateTagForScriptFormula(SF_N);
                    return(Evaluate(powerSNO, relativeTag, attributes, rand, out result));
                }
                else if (numb1 >= 63 && numb1 <= 72)     // known gamebalance power table id range
                {
                    result = BinaryIntToFloat(numb1);    // simply store id, used later by Table()
                    return(true);
                }
                else
                {
                    Logger.Error("unknown identifier");
                    result = 0;
                    return(false);
                }
            }
        }
Пример #3
0
        // FIXME: Hardcoded hell. /komiga
        public void Die(Player player)
        {
            /*var killAni = new int[]{
                    0x2cd7,
                    0x2cd4,
                    0x01b378,
                    0x2cdc,
                    0x02f2,
                    0x2ccf,
                    0x2cd0,
                    0x2cd1,
                    0x2cd2,
                    0x2cd3,
                    0x2cd5,
                    0x01b144,
                    0x2cd6,
                    0x2cd8,
                    0x2cda,
                    0x2cd9
            };*/
            this.World.BroadcastIfRevealed(new PlayEffectMessage()
            {
                ActorId = this.DynamicID,
                Effect = Effect.Hit,
                OptionalParameter = 0x2,
            }, this);

            this.World.BroadcastIfRevealed(new PlayEffectMessage()
            {
                ActorId = this.DynamicID,
                Effect = Effect.Unknown12,
            }, this);

            this.World.BroadcastIfRevealed(new PlayHitEffectMessage()
            {
                ActorID = this.DynamicID,
                HitDealer = player.DynamicID,
                Field2 = 0x2,
                Field3 = false,
            }, this);

            this.World.BroadcastIfRevealed(new FloatingNumberMessage()
            {
                ActorID = this.DynamicID,
                Number = 9001.0f,
                Type = FloatingNumberMessage.FloatType.White,
            }, this);

            this.World.BroadcastIfRevealed(new ANNDataMessage(Opcodes.ANNDataMessage13)
            {
                ActorID = this.DynamicID
            }, this);

            player.UpdateExp(this.Attributes[GameAttribute.Experience_Granted]);
            player.ExpBonusData.Update(player.GBHandle.Type, this.GBHandle.Type);

            this.World.BroadcastIfRevealed(new PlayAnimationMessage()
            {
                ActorID = this.DynamicID,
                Field1 = 0xb,
                Field2 = 0,
                tAnim = new PlayAnimationMessageSpec[1]
                {
                    new PlayAnimationMessageSpec()
                    {
                        Field0 = 0x2,
                        Field1 = AnimationSet.GetRandomDeath(),//killAni[RandomHelper.Next(killAni.Length)],
                        Field2 = 0x0,
                        Field3 = 1f
                    }
                }
            }, this);

            this.World.BroadcastIfRevealed(new ANNDataMessage(Opcodes.ANNDataMessage24)
            {
                ActorID = this.DynamicID,
            }, this);

            GameAttributeMap attribs = new GameAttributeMap();
            attribs[GameAttribute.Hitpoints_Cur] = 0f;
            attribs[GameAttribute.Could_Have_Ragdolled] = true;
            attribs[GameAttribute.Deleted_On_Server] = true;

            foreach (var msg in attribs.GetMessageList(this.DynamicID))
                this.World.BroadcastIfRevealed(msg, this);

            this.World.SpawnRandomItemDrop(player, this.Position);
            this.World.SpawnGold(player, this.Position);
            if (RandomHelper.Next(1, 100) < 20)
                this.World.SpawnHealthGlobe(player, this.Position);
            this.PlayLore();
            this.Destroy();
        }
Пример #4
0
        public void UpdateExp(int addedExp)
        {
            GameAttributeMap attribs = new GameAttributeMap();

            this.Attributes[GameAttribute.Experience_Next] -= addedExp;

            // Levelup
            if ((this.Attributes[GameAttribute.Experience_Next] <= 0) && (this.Attributes[GameAttribute.Level] < this.Attributes[GameAttribute.Level_Cap]))
            {
                this.Attributes[GameAttribute.Level]++;
                this.Properties.LevelUp();
                if (this.Attributes[GameAttribute.Level] < this.Attributes[GameAttribute.Level_Cap]) { this.Attributes[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next] + LevelBorders[this.Attributes[GameAttribute.Level]]; }
                else { this.Attributes[GameAttribute.Experience_Next] = 0; }

                // Notes on attribute increment algorithm:
                // Precision: Barbarian => +1, else => +2
                // Defense:   Wizard or Demon Hunter => (lvl+1)%2+1, else => +2
                // Vitality:  Wizard or Demon Hunter => lvl%2+1, Barbarian => +2, else +1
                // Attack:    All +2
                // Attack
                this.Attributes[GameAttribute.Attack] += 2f;
                // Precision
                if (this.Properties.Class == ToonClass.Barbarian)
                {
                    this.Attributes[GameAttribute.Precision] += 1f;
                }
                else
                {
                    this.Attributes[GameAttribute.Precision] += 2f;
                }
                // Vitality and Defense
                if ((this.Properties.Class == ToonClass.Wizard) || (this.Properties.Class == ToonClass.DemonHunter))
                {
                    this.Attributes[GameAttribute.Vitality] += (this.Attributes[GameAttribute.Level] % 2) + 1f;
                    this.Attributes[GameAttribute.Defense] += ((this.Attributes[GameAttribute.Level] + 1) % 2) + 1f;
                }
                else if (this.Properties.Class == ToonClass.Barbarian)
                {
                    this.Attributes[GameAttribute.Vitality] += 2f;
                    this.Attributes[GameAttribute.Defense] += 2f;
                }
                else
                {
                    this.Attributes[GameAttribute.Vitality] += 1f;
                    this.Attributes[GameAttribute.Defense] += 2f;
                }

                attribs[GameAttribute.Level] = this.Attributes[GameAttribute.Level];
                attribs[GameAttribute.Defense] = this.Attributes[GameAttribute.Defense];
                attribs[GameAttribute.Vitality] = this.Attributes[GameAttribute.Vitality];
                attribs[GameAttribute.Precision] = this.Attributes[GameAttribute.Precision];
                attribs[GameAttribute.Attack] = this.Attributes[GameAttribute.Attack];
                attribs[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next];
                attribs.SendMessage(this.InGameClient, this.DynamicID);

                this.InGameClient.SendMessage(new PlayerLevel()
                {
                    Id = 0x98,
                    Field0 = 0x00000000,
                    Field1 = this.Attributes[GameAttribute.Level],
                });

                this.InGameClient.SendMessage(new PlayEffectMessage()
                {
                    Id = 0x7a,
                    ActorID = this.DynamicID,
                    Field1 = 6,
                });
                /*this.InGameClient.SendMessage(new PlayEffectMessage()
                {
                    Id = 0x7a,
                    ActorID = this.DynamicID,
                    Field1 = 32,
                    Field2 = LevelUpEffects[this.Attributes[GameAttribute.Level]],
                });*/

                this.World.BroadcastGlobal(new PlayEffectMessage()
                {
                    Id = 0x7a,
                    ActorID = this.DynamicID,
                    Field1 = 32,
                    Field2 = LevelUpEffects[this.Attributes[GameAttribute.Level]],
                });
            }

            // constant 0 exp at Level_Cap
            if (this.Attributes[GameAttribute.Experience_Next] < 0) { this.Attributes[GameAttribute.Experience_Next] = 0; }

            attribs[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next];
            attribs.SendMessage(this.InGameClient, this.DynamicID);

            //this.Attributes.SendMessage(this.InGameClient, this.DynamicID); kills the player atm
        }
Пример #5
0
        // FIXME: Hardcoded crap
        public override void OnEnter(World world)
        {
            this.World.Reveal(this);

            // FIXME: hackedy hack
            var attribs = new GameAttributeMap();
            attribs[GameAttribute.Hitpoints_Healed_Target] = 76f;
            attribs.SendMessage(InGameClient, this.DynamicID);
        }
Пример #6
0
        public static bool Evaluate(int powerSNO, TagKeyScript scriptTag, GameAttributeMap attributes, Random rand, out float result)
        {
            result = 0;

            ScriptFormula scriptFormula = FindScriptFormula(powerSNO, scriptTag);

            if (scriptFormula == null)
            {
                //Logger.Error("could not find script tag {0} in power {1}", scriptTag.ID, powerSNO);
                return(false);
            }

            byte[]        script = scriptFormula.OpCodeArray;
            Stack <float> stack = new Stack <float>(4);  // analysis of all stack formulas found the biggest stack is currently 11
            int           pos = 0;
            float         numb1, numb2, numb3;
            float         temp;

            while (pos < script.Length)
            {
                switch (script[pos])
                {
                case 0:     // return
                    if (StackUnderflow(stack, 1))
                    {
                        return(false);
                    }
                    result = stack.Pop();
                    return(true);

                case 1:     // function
                    pos += 4;
                    switch (script[pos])
                    {
                    case 0:         // Min()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(Math.Min(numb1, numb2));
                        break;

                    case 1:         // Max()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(Math.Max(numb1, numb2));
                        break;

                    case 2:         // Pin()
                        if (StackUnderflow(stack, 3))
                        {
                            return(false);
                        }
                        numb3 = stack.Pop();
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        if (numb2 > numb1)
                        {
                            stack.Push(numb2);
                        }
                        else if (numb1 > numb3)
                        {
                            stack.Push(numb3);
                        }
                        else
                        {
                            stack.Push(numb1);
                        }

                        break;

                    case 3:         // RandomIntMinRange()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(rand.Next((int)numb1, (int)numb1 + (int)numb2));
                        break;

                    case 4:         // RandomIntMinMax()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(rand.Next((int)numb1, (int)numb2));
                        break;

                    case 5:         // Floor()
                        if (StackUnderflow(stack, 1))
                        {
                            return(false);
                        }
                        numb1 = stack.Pop();
                        stack.Push((float)Math.Floor(numb1));
                        break;

                    case 9:         // RandomFloatMinRange()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 + (float)rand.NextDouble() * numb2);
                        break;

                    case 10:         // RandomFloatMinMax()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 + (float)rand.NextDouble() * (numb2 - numb1));
                        break;

                    case 11:         // Table()
                        if (StackUnderflow(stack, 2))
                        {
                            return(false);
                        }
                        float index   = stack.Pop();
                        float tableID = stack.Pop();
                        if (!LookupBalanceTable(tableID, index, out temp))
                        {
                            return(false);
                        }
                        stack.Push(temp);
                        break;

                    default:
                        Logger.Error("Unimplemented function");
                        return(false);
                    }
                    break;

                case 5:     // external identifier
                    if (!LoadIdentifier(powerSNO, scriptTag, attributes, rand,
                                        BitConverter.ToInt32(script, pos + 4 * 1),
                                        BitConverter.ToInt32(script, pos + 4 * 2),
                                        BitConverter.ToInt32(script, pos + 4 * 3),
                                        BitConverter.ToInt32(script, pos + 4 * 4),
                                        out temp))
                    {
                        return(false);
                    }

                    stack.Push(temp);
                    pos += 4 * 4;
                    break;

                case 6:     // push float
                    pos += 4;
                    stack.Push(BitConverter.ToSingle(script, pos));
                    break;

                case 8:     // operator >
                    if (StackUnderflow(stack, 2))
                    {
                        return(false);
                    }
                    numb2 = stack.Pop();
                    numb1 = stack.Pop();
                    stack.Push(numb1 > numb2 ? 1 : 0);
                    break;

                case 11:     // operator +
                    if (StackUnderflow(stack, 2))
                    {
                        return(false);
                    }
                    numb2 = stack.Pop();
                    numb1 = stack.Pop();
                    stack.Push(numb1 + numb2);
                    break;

                case 12:     // operator -
                    if (StackUnderflow(stack, 2))
                    {
                        return(false);
                    }
                    numb2 = stack.Pop();
                    numb1 = stack.Pop();
                    stack.Push(numb1 - numb2);
                    break;

                case 13:     // operator *
                    if (StackUnderflow(stack, 2))
                    {
                        return(false);
                    }
                    numb2 = stack.Pop();
                    numb1 = stack.Pop();
                    stack.Push(numb1 * numb2);
                    break;

                case 14:     // operator /
                    if (StackUnderflow(stack, 2))
                    {
                        return(false);
                    }
                    numb2 = stack.Pop();
                    numb1 = stack.Pop();
                    if (numb2 == 0f)
                    {
                        Logger.Error("Division by zero, 0 pushed to stack instead of divide result");
                        stack.Push(0f);
                    }
                    else
                    {
                        stack.Push(numb1 / numb2);
                    }
                    break;

                case 16:     // operator -(unary)
                    if (StackUnderflow(stack, 1))
                    {
                        return(false);
                    }
                    numb1 = stack.Pop();
                    stack.Push(-numb1);
                    break;

                case 17:     // operator ?:
                    if (StackUnderflow(stack, 3))
                    {
                        return(false);
                    }
                    numb3 = stack.Pop();
                    numb2 = stack.Pop();
                    numb1 = stack.Pop();
                    stack.Push(numb1 != 0 ? numb2 : numb3);
                    break;

                default:
                    Logger.Error("Unimplemented OpCode({0})", script[pos]);
                    return(false);
                }
                pos += 4;
            }

            // HACK: ignore bad formula
            if (powerSNO == Skills.Skills.Barbarian.FurySpenders.Whirlwind &&
                scriptTag.ID == 266560) // ScriptFormula(4)
            {
                return(true);
            }

            Logger.Error("script finished without return opcode");
            return(false);
        }
Пример #7
0
        // FIXME: Hardcoded hell. /komiga
        public void Die(Player player)
        {
            /*var killAni = new int[]{
             *      0x2cd7,
             *      0x2cd4,
             *      0x01b378,
             *      0x2cdc,
             *      0x02f2,
             *      0x2ccf,
             *      0x2cd0,
             *      0x2cd1,
             *      0x2cd2,
             *      0x2cd3,
             *      0x2cd5,
             *      0x01b144,
             *      0x2cd6,
             *      0x2cd8,
             *      0x2cda,
             *      0x2cd9
             * };*/
            this.World.BroadcastIfRevealed(new PlayEffectMessage()
            {
                ActorId           = this.DynamicID,
                Effect            = Effect.Hit,
                OptionalParameter = 0x2,
            }, this);

            this.World.BroadcastIfRevealed(new PlayEffectMessage()
            {
                ActorId = this.DynamicID,
                Effect  = Effect.Unknown12,
            }, this);

            this.World.BroadcastIfRevealed(new PlayHitEffectMessage()
            {
                ActorID   = this.DynamicID,
                HitDealer = player.DynamicID,
                Field2    = 0x2,
                Field3    = false,
            }, this);

            this.World.BroadcastIfRevealed(new FloatingNumberMessage()
            {
                ActorID = this.DynamicID,
                Number  = 9001.0f,
                Type    = FloatingNumberMessage.FloatType.White,
            }, this);

            this.World.BroadcastIfRevealed(new ANNDataMessage(Opcodes.ANNDataMessage13)
            {
                ActorID = this.DynamicID
            }, this);

            this.World.BroadcastIfRevealed(new PlayAnimationMessage()
            {
                ActorID = this.DynamicID,
                Field1  = 0xb,
                Field2  = 0,
                tAnim   = new PlayAnimationMessageSpec[1]
                {
                    new PlayAnimationMessageSpec()
                    {
                        Field0 = 0x2,
                        Field1 = AnimationSet.GetRandomDeath(),//killAni[RandomHelper.Next(killAni.Length)],
                        Field2 = 0x0,
                        Field3 = 1f
                    }
                }
            }, this);

            this.World.BroadcastIfRevealed(new ANNDataMessage(Opcodes.ANNDataMessage24)
            {
                ActorID = this.DynamicID,
            }, this);

            GameAttributeMap attribs = this.Attributes; //TODO change it /fasbat

            attribs[GameAttribute.Hitpoints_Cur]        = 0f;
            attribs[GameAttribute.Could_Have_Ragdolled] = true;
            attribs[GameAttribute.Deleted_On_Server]    = true;

            attribs.BroadcastChangedIfRevealed();

            // Spawn Random item and give exp for each player in range
            List <Player> players = this.GetPlayersInRange(26f);

            foreach (Player plr in players)
            {
                plr.UpdateExp(this.Attributes[GameAttribute.Experience_Granted]);
                this.World.SpawnRandomItemDrop(this, plr);
            }

            player.ExpBonusData.Update(player.GBHandle.Type, this.GBHandle.Type);
            this.World.SpawnGold(this, player);
            if (RandomHelper.Next(1, 100) < 20)
            {
                this.World.SpawnHealthGlobe(this, player, this.Position);
            }
            this.PlayLore();
            this.Destroy();
        }
Пример #8
0
        // FIXME: Hardcoded crap
        public override void OnEnter(World world)
        {
            this.World.Reveal(this);

            // This "tick" stuff is somehow required to use these values.. /komiga
            this.InGameClient.SendMessage(new DWordDataMessage() // TICK
            {
                Id = 0x0089,
                Field0 = 0x00000077,
            });
            this.InGameClient.FlushOutgoingBuffer();

            // FIXME: hackedy hack
            var attribs = new GameAttributeMap();
            attribs[GameAttribute.Hitpoints_Healed_Target] = 76f;
            attribs.SendMessage(InGameClient, this.DynamicID);

            this.InGameClient.PacketId += 40 * 2;
            this.InGameClient.SendMessage(new DWordDataMessage()
            {
                Id = 0x89,
                Field0 = 0x0000007D //this.InGameClient.PacketId,
            });
            this.InGameClient.FlushOutgoingBuffer();
        }
Пример #9
0
        public void UpdateExp(int addedExp)
        {
            GameAttributeMap attribs = new GameAttributeMap();

            this.Attributes[GameAttribute.Experience_Next] -= addedExp;

            // Levelup
            if ((this.Attributes[GameAttribute.Experience_Next] <= 0) && (this.Attributes[GameAttribute.Level] < this.Attributes[GameAttribute.Level_Cap]))
            {
                this.Attributes[GameAttribute.Level]++;
                if (this.Attributes[GameAttribute.Level] < this.Attributes[GameAttribute.Level_Cap]) { this.Attributes[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next] + LevelBorders[this.Attributes[GameAttribute.Level]]; }
                else { this.Attributes[GameAttribute.Experience_Next] = 0; }

                // todo: not always adding 2/2/2/1 on Levelup
                this.Attributes[GameAttribute.Defense] = 10f + (this.Attributes[GameAttribute.Level] - 1f) * 2f;
                this.Attributes[GameAttribute.Vitality] = 9f + (this.Attributes[GameAttribute.Level] - 1f) * 1f;
                this.Attributes[GameAttribute.Precision] = 11f + (this.Attributes[GameAttribute.Level] - 1f) * 2f;
                this.Attributes[GameAttribute.Attack] = 10f + (this.Attributes[GameAttribute.Level] - 1f) * 2f;
                attribs[GameAttribute.Level] = this.Attributes[GameAttribute.Level];
                attribs[GameAttribute.Defense] = this.Attributes[GameAttribute.Defense];
                attribs[GameAttribute.Vitality] = this.Attributes[GameAttribute.Vitality];
                attribs[GameAttribute.Precision] = this.Attributes[GameAttribute.Precision];
                attribs[GameAttribute.Attack] = this.Attributes[GameAttribute.Attack];
                attribs[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next];
                attribs.SendMessage(this.InGameClient, this.DynamicID);

                this.InGameClient.SendMessage(new PlayerLevel()
                {
                    Id = 0x98,
                    Field0 = 0x00000000,
                    Field1 = this.Attributes[GameAttribute.Level],
                });

                this.InGameClient.SendMessage(new PlayEffectMessage()
                {
                    Id = 0x7a,
                    ActorID = this.DynamicID,
                    Field1 = 6,
                });
                this.InGameClient.SendMessage(new PlayEffectMessage()
                {
                    Id = 0x7a,
                    ActorID = this.DynamicID,
                    Field1 = 32,
                    Field2 = LevelUpEffects[this.Attributes[GameAttribute.Level]],
                });
            }

            // constant 0 exp at Level_Cap
            if (this.Attributes[GameAttribute.Experience_Next] < 0) { this.Attributes[GameAttribute.Experience_Next] = 0; }

            attribs[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next];
            attribs.SendMessage(this.InGameClient, this.DynamicID);

            //this.Attributes.SendMessage(this.InGameClient, this.DynamicID); kills the player atm
        }
Пример #10
0
        // FIXME: Hardcoded crap
        // FIXME: The new player stuff only needs to be called when the player joins the game
        public override void OnEnter(World world)
        {
            this.World.Reveal(this);

            // Notify the client of the new player
            InGameClient.SendMessage(new NewPlayerMessage
            {
                Field0 = 0x00000000, //Party frame (0x00000000 hide, 0x00000001 show)
                Field1 = "", //Owner name?
                ToonName = this.Properties.Name,
                Field3 = 0x00000002, //party frame class
                Field4 = 0x00000004, //party frame level
                snoActorPortrait = this.ClassSNO, //party frame portrait
                Field6 = 0x00000001,
                StateData = this.GetStateData(),
                Field8 = false, //announce party join
                Field9 = 0x00000001,
                ActorID = this.DynamicID,
            });

            InGameClient.SendMessage(new ACDCollFlagsMessage
            {
                ActorID = this.DynamicID,
                CollFlags = 0x00000000,
            });

            this.Attributes.SendMessage(InGameClient, this.DynamicID);

            // TODO: Pretty sure most of this stuff can be (and probably should be) put into Actor.Reveal()
            this.InGameClient.SendMessage(new ACDGroupMessage()
            {
                ActorID = this.DynamicID,
                Field1 = -1,
                Field2 = -1,
            });

            this.InGameClient.SendMessage(new ANNDataMessage(Opcodes.ANNDataMessage7)
            {
                ActorID = this.DynamicID,
            });

            this.InGameClient.SendMessage(new ACDTranslateFacingMessage(Opcodes.ACDTranslateFacingMessage1)
            {
                ActorID = this.DynamicID,
                Angle = 3.022712f,
                Field2 = false,
            });

            this.InGameClient.SendMessage(new PlayerEnterKnownMessage()
            {
                Field0 = 0x00000000,
                PlayerID = this.DynamicID,
            });

            this.InGameClient.SendMessage(new PlayerActorSetInitialMessage()
            {
                PlayerID = this.DynamicID,
                Field1 = 0x00000000,
            });

            this.InGameClient.SendMessage(new SNONameDataMessage()
            {
                Name = new SNOName()
                {
                    Group = 0x00000001,
                    Handle = this.ClassSNO,
                },
            });
            this.InGameClient.FlushOutgoingBuffer();

            this.InGameClient.SendMessage(new PlayerWarpedMessage()
            {
                Field0 = 9,
                Field1 = 0f,
            });

            // This "tick" stuff is somehow required to use these values.. /komiga
            this.InGameClient.SendMessage(new DWordDataMessage() // TICK
            {
                Id = 0x0089,
                Field0 = 0x00000077,
            });
            this.InGameClient.FlushOutgoingBuffer();

            // FIXME: hackedy hack
            var attribs = new GameAttributeMap();
            attribs[GameAttribute.Hitpoints_Healed_Target] = 76f;
            attribs.SendMessage(InGameClient, this.DynamicID);

            this.InGameClient.PacketId += 40 * 2;
            this.InGameClient.SendMessage(new DWordDataMessage()
            {
                Id = 0x89,
                Field0 = 0x0000007D //this.InGameClient.PacketId,
            });
            this.InGameClient.FlushOutgoingBuffer();
        }
Пример #11
0
        public void Handle(GameClient client)
        {
            var player = client.Player;
            switch (this.Id)
            {
                case 0x0030: // Sent with DwordDataMessage(0x0125, Value:0) and SimpleMessage(0x0125)
                    {
                        // What the dickens is this stuff
                        #region hardcoded1
                        #region Player Attribute Values

                        GameAttributeMap attributes = new GameAttributeMap();
                        attributes[GameAttribute.Banter_Cooldown, 0xFFFFF] = 0x000007C9;
                        attributes[GameAttribute.Buff_Active, 0x20CBE] = true;
                        attributes[GameAttribute.Buff_Active, 0x33C40] = false;
                        attributes[GameAttribute.Immobolize] = false;
                        attributes[GameAttribute.Untargetable] = false;
                        attributes[GameAttribute.CantStartDisplayedPowers] = false;
                        attributes[GameAttribute.Buff_Icon_Start_Tick0, 0x20CBE] = 0xC1;
                        attributes[GameAttribute.Disabled] = false;
                        attributes[GameAttribute.Hidden] = false;
                        attributes[GameAttribute.Buff_Icon_Count0, 0x33C40] = 0;
                        attributes[GameAttribute.Buff_Icon_End_Tick0, 0x20CBE] = 0x7C9;
                        attributes[GameAttribute.Loading] = false;
                        attributes[GameAttribute.Buff_Icon_End_Tick0, 0x33C40] = 0;
                        attributes[GameAttribute.Invulnerable] = false;
                        attributes[GameAttribute.Buff_Icon_Count0, 0x20CBE] = 1;
                        attributes[GameAttribute.Buff_Icon_Start_Tick0, 0x33C40] = 0;
                        attributes.SendMessage(client, player.DynamicID);

                        #endregion

                        client.SendMessage(new ACDCollFlagsMessage()
                        {
                            ActorID = player.DynamicID,
                            CollFlags = 0x00000008,
                        });

                        client.SendMessage(new DWordDataMessage()
                        {
                            Id = 0x0089,
                            Field0 = 0x000000C1,
                        });
                        #endregion
                        
                        #region hardcoded2
                        // NOTE: This is very similar to ACDEnterKnown fields
                        // TODO: Map proper values from the actor..
                        client.SendMessage(new TrickleMessage()
                        {
                            ActorId = player.DynamicID,
                            ActorSNO = client.Player.ClassSNO,
                            WorldLocation = new WorldPlace()
                            {
                                Position = new Vector3D()
                                {
                                    X = 3143.75f,
                                    Y = 2828.75f,
                                    Z = 59.07559f,
                                },
                                WorldID = client.Player.World.DynamicID,
                            },
                            PlayerIndex = 0x00000000,
                            LevelAreaSNO = 0x00026186,
                            Field5 = 1f,
                            Field6 = 0x00000001,
                            Field7 = 0x00000024,
                            Field10 = unchecked((int)0x8DFA5D13),
                            StringListSNO = 0x0000F063,
                        });

                        client.SendMessage(new DWordDataMessage()
                        {
                            Id = 0x0089,
                            Field0 = 0x000000D1,
                        });
                        #endregion
                        
                    }
                    break;
                case 0x0028: // Logout complete (sent when delay timer expires on client side)
                    //if (client.IsLoggingOut)
                    //{
                    //    client.SendMessageNow(new QuitGameMessage()
                    //    {
                    //        Id = 0x0003,
                    //        // Field0 - quit reason?
                    //        // 0 - logout
                    //        // 1 - kicked by party leader
                    //        // 2 - disconnected due to client-server (version?) missmatch
                    //        PlayerIndex = 0,
                    //    });
                    //}
                    break;
                default:
                    throw new NotImplementedException();
            }
        }
Пример #12
0
        public static bool Evaluate(int powerSNO, TagKeyScript scriptTag, GameAttributeMap attributes, Random rand, out float result)
        {
            result = 0;

            ScriptFormula scriptFormula = FindScriptFormula(powerSNO, scriptTag);
            if (scriptFormula == null)
            {
                //Logger.Error("could not find script tag {0} in power {1}", scriptTag.ID, powerSNO);
                return false;
            }

            byte[] script = scriptFormula.OpCodeArray;
            Stack<float> stack = new Stack<float>(4);  // analysis of all stack formulas found the biggest stack is currently 11
            int pos = 0;
            float numb1, numb2, numb3;
            float temp;
            while (pos < script.Length)
            {
                switch (script[pos])
                {
                    case 0: // return
                        if (StackUnderflow(stack, 1))
                            return false;
                        result = stack.Pop();
                        return true;

                    case 1: // function
                        pos += 4;
                        switch (script[pos])
                        {
                            case 0: // Min()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                stack.Push(Math.Min(numb1, numb2));
                                break;

                            case 1: // Max()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                stack.Push(Math.Max(numb1, numb2));
                                break;

                            case 2: // Pin()
                                if (StackUnderflow(stack, 3))
                                    return false;
                                numb3 = stack.Pop();
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                if (numb2 > numb1)
                                    stack.Push(numb2);
                                else if (numb1 > numb3)
                                    stack.Push(numb3);
                                else
                                    stack.Push(numb1);

                                break;

                            case 3: // RandomIntMinRange()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                stack.Push(rand.Next((int)numb1, (int)numb1 + (int)numb2));
                                break;

                            case 4: // RandomIntMinMax()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                stack.Push(rand.Next((int)numb1, (int)numb2));
                                break;

                            case 5: // Floor()
                                if (StackUnderflow(stack, 1))
                                    return false;
                                numb1 = stack.Pop();
                                stack.Push((float)Math.Floor(numb1));
                                break;

                            case 9: // RandomFloatMinRange()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                stack.Push(numb1 + (float)rand.NextDouble() * numb2);
                                break;

                            case 10: // RandomFloatMinMax()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                numb2 = stack.Pop();
                                numb1 = stack.Pop();
                                stack.Push(numb1 + (float)rand.NextDouble() * (numb2 - numb1));
                                break;

                            case 11: // Table()
                                if (StackUnderflow(stack, 2))
                                    return false;
                                float index = stack.Pop();
                                float tableID = stack.Pop();
                                if (!LookupBalanceTable(tableID, index, out temp))
                                    return false;
                                stack.Push(temp);
                                break;

                            default:
                                Logger.Error("Unimplemented function");
                                return false;
                        }
                        break;
                    case 5: // external identifier
                        if (!LoadIdentifier(powerSNO, scriptTag, attributes, rand,
                                            BitConverter.ToInt32(script, pos + 4 * 1),
                                            BitConverter.ToInt32(script, pos + 4 * 2),
                                            BitConverter.ToInt32(script, pos + 4 * 3),
                                            BitConverter.ToInt32(script, pos + 4 * 4),
                                            out temp))
                            return false;

                        stack.Push(temp);
                        pos += 4 * 4;
                        break;

                    case 6: // push float
                        pos += 4;
                        stack.Push(BitConverter.ToSingle(script, pos));
                        break;

                    case 8: // operator >
                        if (StackUnderflow(stack, 2))
                            return false;
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 > numb2 ? 1 : 0);
                        break;

                    case 11: // operator +
                        if (StackUnderflow(stack, 2))
                            return false;
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 + numb2);
                        break;

                    case 12: // operator -
                        if (StackUnderflow(stack, 2))
                            return false;
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 - numb2);
                        break;

                    case 13: // operator *
                        if (StackUnderflow(stack, 2))
                            return false;
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 * numb2);
                        break;

                    case 14: // operator /
                        if (StackUnderflow(stack, 2))
                            return false;
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        if (numb2 == 0f)
                        {
                            Logger.Error("Division by zero, 0 pushed to stack instead of divide result");
                            stack.Push(0f);
                        }
                        else
                        {
                            stack.Push(numb1 / numb2);
                        }
                        break;

                    case 16: // operator -(unary)
                        if (StackUnderflow(stack, 1))
                            return false;
                        numb1 = stack.Pop();
                        stack.Push(-numb1);
                        break;

                    case 17: // operator ?:
                        if (StackUnderflow(stack, 3))
                            return false;
                        numb3 = stack.Pop();
                        numb2 = stack.Pop();
                        numb1 = stack.Pop();
                        stack.Push(numb1 != 0 ? numb2 : numb3);
                        break;

                    default:
                        Logger.Error("Unimplemented OpCode({0})", script[pos]);
                        return false;
                }
                pos += 4;
            }

            // HACK: ignore bad formula
            if (powerSNO == Skills.Skills.Barbarian.FurySpenders.Whirlwind &&
                scriptTag.ID == 266560) // ScriptFormula(4)
            {
                return true;
            }

            Logger.Error("script finished without return opcode");
            return false;
        }
Пример #13
0
        private static bool LoadAttribute(int powerSNO, GameAttributeMap attributes, int attributeId, out float result)
        {
            GameAttribute attr = GameAttribute.Attributes[attributeId];
            bool needs_key = _powerKeyedAttributes.Contains(attributeId);

            if (attr is GameAttributeF)
            {
                if (needs_key) result = attributes[(GameAttributeF)attr, powerSNO];
                else result = attributes[(GameAttributeF)attr];

                return true;
            }
            else if (attr is GameAttributeI)
            {
                if (needs_key) result = (float)attributes[(GameAttributeI)attr, powerSNO];
                else result = (float)attributes[(GameAttributeI)attr];

                return true;
            }
            else if (attr is GameAttributeB)
            {
                if (needs_key) result = attributes[(GameAttributeB)attr, powerSNO] ? 1 : 0;
                else result = attributes[(GameAttributeB)attr] ? 1 : 0;

                return true;
            }
            else
            {
                Logger.Error("invalid attribute {0}", attributeId);
                result = 0;
                return false;
            }
        }
Пример #14
0
        private static bool LoadIdentifier(int powerSNO, TagKeyScript scriptTag, GameAttributeMap attributes, Random rand,
                                           int numb1, int numb2, int numb3, int numb4,
                                           out float result)
        {
            switch (numb1)
            {
                case 0:
                    return LoadAttribute(powerSNO, attributes, numb2, out result);

                case 1: // slevel
                    result = attributes[GameAttribute.Skill, powerSNO];
                    return true;

                case 22: // absolute power formula ref
                    return Evaluate(numb2, new TagKeyScript(numb3), attributes, rand, out result);

                default:
                    if (numb1 >= 23 && numb1 <= 62) // SF_N, relative power formula ref
                    {
                        int SF_N = numb1 - 23;
                        TagKeyScript relativeTag = PowerTagHelper.GenerateTagForScriptFormula(SF_N);
                        return Evaluate(powerSNO, relativeTag, attributes, rand, out result);
                    }
                    else if (numb1 >= 63 && numb1 <= 72) // known gamebalance power table id range
                    {
                        result = BinaryIntToFloat(numb1); // simply store id, used later by Table()
                        return true;
                    }
                    else
                    {
                        Logger.Error("unknown identifier");
                        result = 0;
                        return false;
                    }
            }
        }
Пример #15
0
        public void UpdateExp(int addedExp)
        {
            GameAttributeMap attribs = new GameAttributeMap();

            this.Attributes[GameAttribute.Experience_Next] -= addedExp;

            // Levelup
            if ((this.Attributes[GameAttribute.Experience_Next] <= 0) && (this.Attributes[GameAttribute.Level] < this.Attributes[GameAttribute.Level_Cap]))
            {
                this.Attributes[GameAttribute.Level]++;
                this.Properties.LevelUp();
                if (this.Attributes[GameAttribute.Level] < this.Attributes[GameAttribute.Level_Cap]) { this.Attributes[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next] + LevelBorders[this.Attributes[GameAttribute.Level]]; }
                else { this.Attributes[GameAttribute.Experience_Next] = 0; }

                // 4 main attributes are incremented according to class
                this.Attributes[GameAttribute.Attack] += this.AttackIncrement;
                this.Attributes[GameAttribute.Precision] += this.PrecisionIncrement;
                this.Attributes[GameAttribute.Vitality] += this.VitalityIncrement;
                this.Attributes[GameAttribute.Defense] += this.DefenseIncrement;

                // Hitpoints from level may actually change. This needs to be verified by someone with the beta.
                //this.Attributes[GameAttribute.Hitpoints_Total_From_Level] = this.Attributes[GameAttribute.Level] * this.Attributes[GameAttribute.Hitpoints_Factor_Level];
                
                // For now, hit points are based solely on vitality and initial hitpoints received.
                // This will have to change when hitpoint bonuses from items are implemented.
                this.Attributes[GameAttribute.Hitpoints_Total_From_Vitality] = this.Attributes[GameAttribute.Vitality] * this.Attributes[GameAttribute.Hitpoints_Factor_Vitality];
                this.Attributes[GameAttribute.Hitpoints_Max] = GetMaxTotalHitpoints();
                this.Attributes[GameAttribute.Hitpoints_Max_Total] = GetMaxTotalHitpoints();

                // On level up, health is set to max
                this.Attributes[GameAttribute.Hitpoints_Cur] = this.Attributes[GameAttribute.Hitpoints_Max_Total];

                attribs[GameAttribute.Level] = this.Attributes[GameAttribute.Level];
                attribs[GameAttribute.Defense] = this.Attributes[GameAttribute.Defense];
                attribs[GameAttribute.Vitality] = this.Attributes[GameAttribute.Vitality];
                attribs[GameAttribute.Precision] = this.Attributes[GameAttribute.Precision];
                attribs[GameAttribute.Attack] = this.Attributes[GameAttribute.Attack];
                attribs[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next];
                attribs[GameAttribute.Hitpoints_Total_From_Vitality] = this.Attributes[GameAttribute.Hitpoints_Total_From_Vitality];
                attribs[GameAttribute.Hitpoints_Max_Total] = this.Attributes[GameAttribute.Hitpoints_Max_Total];
                attribs[GameAttribute.Hitpoints_Max] = this.Attributes[GameAttribute.Hitpoints_Max];
                attribs[GameAttribute.Hitpoints_Cur] = this.Attributes[GameAttribute.Hitpoints_Cur];

                attribs.SendMessage(this.InGameClient, this.DynamicID);

                this.InGameClient.SendMessage(new PlayerLevel()
                {
                    Id = 0x98,
                    Field0 = 0x00000000,
                    Field1 = this.Attributes[GameAttribute.Level],
                });

                this.InGameClient.SendMessage(new PlayEffectMessage()
                {
                    ActorId = this.DynamicID,
                    Effect = Effect.LevelUp,
                });

                this.World.BroadcastGlobal(new PlayEffectMessage()
                {
                    ActorId = this.DynamicID,
                    Effect = Effect.PlayEffectGroup,
                    OptionalParameter = LevelUpEffects[this.Attributes[GameAttribute.Level]],
                });
            }

            // constant 0 exp at Level_Cap
            if (this.Attributes[GameAttribute.Experience_Next] < 0) { this.Attributes[GameAttribute.Experience_Next] = 0; }

            attribs[GameAttribute.Experience_Next] = this.Attributes[GameAttribute.Experience_Next];
            attribs.SendMessage(this.InGameClient, this.DynamicID);

            //this.Attributes.SendMessage(this.InGameClient, this.DynamicID); kills the player atm
        }
Пример #16
0
 // simple static reresh 
 public void RefreshStatistic()
 {
     var attribs = new GameAttributeMap();
     // min demage
     this.Attributes[GameAttribute.Damage_Weapon_Min_Total_CurrentHand, 0] = this.Attributes[GameAttribute.Damage_Weapon_Min_Total_MainHand, 0];// only main hand "(DualWield_Hand#NONE ? Damage_Weapon_Min_Total_OffHand : Damage_Weapon_Min_Total_MainHand)"
     this.Attributes[GameAttribute.Damage_Min_Subtotal, 0] = this.Attributes[GameAttribute.Damage_Min, 0] + this.Attributes[GameAttribute.Damage_Bonus_Min, 0] + this.Attributes[GameAttribute.Damage_Weapon_Min_Total_CurrentHand, 0];
     this.Attributes[GameAttribute.Damage_Min_Total, 0] = this.Attributes[GameAttribute.Damage_Min_Subtotal, 0] + this.Attributes[GameAttribute.Damage_Type_Percent_Bonus, 0] * this.Attributes[GameAttribute.Damage_Min_Subtotal, 0];
     // delta demage
     this.Attributes[GameAttribute.Damage_Weapon_Delta_Total_CurrentHand, 0] = this.Attributes[GameAttribute.Damage_Weapon_Delta_Total_MainHand, 0];// only main hand "(DualWield_Hand#NONE ? Damage_Weapon_Min_Total_OffHand : Damage_Weapon_Min_Total_MainHand)"
     this.Attributes[GameAttribute.Damage_Delta_Total, 0] = Math.Max(this.Attributes[GameAttribute.Damage_Delta, 0] - this.Attributes[GameAttribute.Damage_Bonus_Min, 0] + this.Attributes[GameAttribute.Damage_Weapon_Delta_Total_CurrentHand, 0], 0);
     // attack speed hack
     this.Attributes[GameAttribute.Attacks_Per_Second_Item_CurrentHand] = this.Attributes[GameAttribute.Attacks_Per_Second_Item_MainHand]; 
     this.Attributes[GameAttribute.Attacks_Per_Second_Total] = this.Attributes[GameAttribute.Attacks_Per_Second_Item_CurrentHand];     
                   
     attribs[GameAttribute.Damage_Min_Total, 0] = this.Attributes[GameAttribute.Damage_Min_Total, 0];
     attribs[GameAttribute.Damage_Delta_Total, 0] = this.Attributes[GameAttribute.Damage_Delta_Total, 0];
     attribs[GameAttribute.Attacks_Per_Second_Total] = this.Attributes[GameAttribute.Attacks_Per_Second_Total];
     attribs.SendMessage(InGameClient, DynamicID);
 }