⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 player_skills.pas

📁 RO模拟器!!适合玩仙境传说的玩家们呦~
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit Player_Skills;

interface

uses
    IniFiles, Classes, SysUtils, Common, List32, MMSystem, Math, Path, Windows;

var
    SKILL_TYPE : Byte;

    { Initialization Procedures }
    procedure parse_skills(tc : TChara; Tick : Cardinal; effect : Integer = 0; UseSP : Boolean = True);

    { Finalization Procedures }
    procedure process_effect(tc : TChara; success : Integer; Tick : Cardinal);
    procedure process_skill_attack(tc : TChara; j : Integer; Tick : Cardinal);
    procedure process_skill_splash_attack(tc : TChara; sl : TStringList; Tick : Cardinal);

    { Calculation Procedures }
    procedure use_sp(tc : TChara; SkillID : word; LV : byte);
    function find_targets(tc : TChara; sl : TStringList; rangefield : Integer) : TStringList;
    function check_allow_pvp(tc : TChara) : Boolean;

    { Skill Procedures - Swordsman }
    function skill_sword_mastery(tc : TChara) : Integer;
    function skill_two_handed_sword_mastery(tc : TChara) : Integer;
    function skill_hp_recovery(tc : TChara; Tick : Cardinal) : Integer;
    function skill_bash(tc : TChara; Tick : Cardinal) : Integer;
    function skill_provoke(tc : TChara) : Integer;
    function skill_magnum_break(tc : TChara; sl : TStringList) : TStringList;
    function skill_endure() : Integer;

    { Skill Procedures - Mage }
    function skill_sp_recovery(tc : TChara; Tick : Cardinal) : Integer;
    function skill_sight(tc : TChara; Tick : Cardinal) : Integer;

    { Skill Procedures - Archer }
    function skill_double_strafe(tc : TChara; Tick : Cardinal) : Integer;

implementation

uses
    Main, Skills;

    procedure parse_skills(tc : TChara; Tick : Cardinal; effect : Integer = 0; UseSP : Boolean = True);
    var
        success : Integer;
        targets : TStringList;
    begin
        SKILL_TYPE := 0;

        if not check_allow_pvp(tc) then Exit;

        targets := TStringList.Create;
        targets.Clear;

        if ( (effect = 1) and (tc.HP <= 0) ) then effect := -1;

        {
            tc.Skill[x].LV must be used for effect skills that have no target.
            tc.MSkill must be used for active skills that have a target.
            tc.Skill[x].LV must be used for passive skills. Also, passive must be true.
        }

        { 2} if (tc.Skill[2].Lv <> 0) and (effect = 2) then success := skill_sword_mastery(tc);
        { 3} if (tc.Skill[3].Lv <> 0) and (effect = 2) then success := skill_two_handed_sword_mastery(tc);
        { 4} if (tc.Skill[4].Lv <> 0) and (effect = 1) then success := skill_hp_recovery(tc, Tick);
        { 5} if (tc.MSkill = 5) and (effect = 0) then success := skill_bash(tc, Tick);
        { 6} if (tc.MSkill = 6) and (effect = 0) then success := skill_provoke(tc);
        { 7} if (tc.MSkill = 7) and (effect = 0) then targets := skill_magnum_break(tc, targets);
        { 8} if (tc.MSkill = 8) and (effect = 0) then success := skill_endure();
        { 9} if (tc.Skill[9].Lv <> 0) and (effect = 1) then success := skill_sp_recovery(tc, Tick);
        {10} if (tc.MSkill = 10) and (effect = 0) then success := skill_sight(tc, Tick);
        {46} if (tc.MSkill = 46) and (effect = 0) then success := skill_double_strafe(tc, Tick);

        {
            Process_Effect Success Codes:
            -1 : Success
            0 : Skill Failed
            1 : Not enough SP
            2 : Not enough HP
            3 : No memo
            4 : In cast delay
            5 : Not enough money
            6 : Weapon is not usable with the skill
            7 : No red gemstone
            8 : No blue gemstone
            9 : No yellow gemstone
        }

        case SKILL_TYPE of
            1: process_effect(tc, success, Tick);
            2: process_effect(tc, success, Tick);
            3: process_skill_attack(tc, success, Tick);
            4: process_skill_splash_attack(tc, targets, Tick);
        end;

        if (UseSP) and ( ( (SKILL_TYPE = 1) and (success = -1) ) or (SKILL_TYPE = 2) or (SKILL_TYPE = 3) ) then begin
            use_sp(tc, tc.MSkill, tc.MUseLV);
        end;

        SKILL_TYPE := 0;
        targets.Free;
    end;

    procedure process_effect(tc : TChara; success : Integer; Tick : Cardinal);
    var
        tm : TMap;
        tc1 : TChara;
        ts : TMob;
        tl : TSkillDB;
    begin
        tm := Map.Objects[Map.IndexOf(tc.Map)] as TMap;
        tl := tc.Skill[tc.MSkill].Data;

        if (success = -1) then begin
            WFIFOW( 0, $011a);
            WFIFOW( 2, tc.MSkill);
            WFIFOW( 4, tc.MUseLV);
            WFIFOL( 6, tc.MTarget);
            WFIFOL(10, tc.ID);
            WFIFOB(14, 1);
        end else begin
            WFIFOW( 0, $0110);
            WFIFOW( 2, tc.MSkill);
            WFIFOW( 4, 0);
            WFIFOW( 6, 0);
            WFIFOB( 8, 0);
            WFIFOB( 9, success);
        end;

        if tc.MTargetType = 0 then begin
            ts := tc.AData;
            if (ts.HP <= 0) and (success = -1) then begin
                SKILL_TYPE := 0;
                Exit;
            end;
            SendBCmd(tm, ts.Point, 15);
        end else begin
            tc1 := tc.AData;
            if (tc1.HP <= 0) and (success = -1) then begin
                SKILL_TYPE := 0;
                Exit;
            end;
            SendBCmd(tm, tc1.Point, 15);

            if (SKILL_TYPE = 2) then begin
                tc1.Skill[tc.MSkill].Tick := Tick + cardinal(tl.Data1[tc.MUseLV]) * 1000;
                tc1.Skill[tc.MSkill].EffectLV := tc.MUseLV;
                tc1.Skill[tc.MSkill].Effect1 := tl.Data2[tc.MUseLV];
                if tc.SkillTick > tc1.Skill[tc.MSkill].Tick then begin
                    tc.SkillTick := tc1.Skill[tc.MSkill].Tick;
                    tc.SkillTickID := tc.MSkill;
                end;
                if tc.MSkill = 61 then tc1.Skill[tc.MSkill].Tick := Tick + cardinal(tl.Data1[tc.MUseLV]) * 110;
                CalcStat(tc1, Tick);
                //if ProcessType = 3 then SendCStat(tc1);
                if (tl.Icon <> 0) and (tl.Icon <> 107) then begin
                    UpdateIcon(tm, tc1, tl.Icon, 1);
                end;
            end;
            
        end;
    end;

    procedure process_skill_attack(tc : TChara; j : Integer; Tick : Cardinal);
    var
        ts : TMob;
        tc1 : TChara;
        tm : TMap;
        tl : TSkillDB;
    begin

        { Placed here to prevent attacking self }
        if tc.AData = tc then Exit;

        if dmg[0] < 0 then dmg[0] := 0;
        if tc.MTargetType = 0 then begin
            ts := tc.AData;
            if ts.HP <= 0 then begin
                SKILL_TYPE := 0;
                Exit;
            end;

            SendCSkillAtk1(tm, tc, ts, Tick, dmg[0], j);
            if not frmMain.DamageProcess1(tm, tc, ts, dmg[0], Tick) then frmMain.StatCalc1(tc, ts, Tick);
        end else begin
            tc1 := tc.AData;
            if tc1.HP <= 0 then begin
                SKILL_TYPE := 0;
                Exit;
            end;

            SendCSkillAtk2(tm, tc, tc1, Tick, dmg[0], j);
            if not frmMain.DamageProcess2(tm, tc, tc1, dmg[0], Tick) then frmMain.StatCalc2(tc, tc1, Tick);
        end;
    end;

    procedure process_skill_splash_attack(tc : TChara; sl : TStringList; Tick : Cardinal);
    var
        k1 : Integer;
        tm : TMap;
        tl : TSkillDB;
        ts : TMob;
        tc1 : TChara;
    begin
        tm := Map.Objects[Map.IndexOf(tc.Map)] as TMap;
        tl := tc.Skill[tc.MSkill].Data;

        tc1 := tc.AData;

        if dmg[0] < 0 then dmg[0] := 0;
        if sl.Count <> 0 then begin
            for k1 := 0 to sl.Count - 1 do begin
                if (tm.CList.IndexOf(StrToInt(sl.Strings[k1])) <> -1) then begin
                    tc1 := sl.Objects[k1] as TChara;
                    if tc1.HP <= 0 then begin
                        SKILL_TYPE := 0;
                        Exit;
                    end;
                    
                    frmMain.DamageCalc3(tm, tc, tc1, Tick, 0, tl.Data1[tc.MUseLV], tl.Element, tl.Data1[tc.MUseLV]);
                    SendCSkillAtk2(tm, tc, tc1, Tick, dmg[0], 1);
                    if not frmMain.DamageProcess2(tm, tc, tc1, dmg[0], Tick) then frmMain.StatCalc2(tc, tc1, Tick);
                end else begin
                    ts := sl.Objects[k1] as TMob;
                    if ts.HP <= 0 then begin
                        SKILL_TYPE := 0;
                        Exit;
                    end;

                    frmMain.DamageCalc1(tm, tc, ts, Tick, 0, tl.Data1[tc.MUseLV], tl.Element, tl.Data1[tc.MUseLV]);
                    SendCSkillAtk1(tm, tc, ts, Tick, dmg[0], 1);
                    if not frmMain.DamageProcess1(tm, tc, ts, dmg[0], Tick) then frmMain.StatCalc1(tc, ts, Tick);
                end;
            end;
        end;
    end;

    procedure use_sp(tc : TChara; SkillID : word; LV : byte);
    begin
        tc.SPAmount := 0;

        if SkillID = 0 then Exit;
        if tc.SP < tc.Skill[SkillID].Data.SP[LV] then Exit;

        tc.SPAmount := tc.Skill[SkillID].Data.SP[LV];

        if tc.LessSP then tc.SPAmount := tc.SPAmount * 70 div 100;
        if tc.NoJamstone then tc.SPAmount := tc.SPAmount * 125 div 100;
        if tc.SPRedAmount > 0 then tc.SPAmount := tc.SPAmount - (tc.Skill[SkillID].Data.SP[LV] * tc.SPRedAmount div 100);

        if (tc.Autocastactive) then begin
            tc.SPAmount := tc.SPAmount * 2 div 3;
            tc.Autocastactive := False;
        end;

        // Golen Thief Bug Card (Alex: Should cards be processed here?)
        if tc.NoTarget then tc.SPAmount := tc.SPAmount * 2;

        tc.SP := tc.SP - tc.SPAmount;

        SendCStat1(tc, 0, 7, tc.SP);
        tc.MMode  := 0;
        tc.MSkill := 0;
        tc.MUseLv := 0;
    end;
    
    function find_targets(tc : TChara; sl : TStringList; rangefield : Integer) : TStringList;
    var
        j1, i1, k1 : Integer;
        tm : TMap;
        tl : TSkillDB;
        xy : TPoint;
        ts : TMob;
        tc1 : TChara;
        mi : MapTbl;
    begin
        tm := Map.Objects[Map.IndexOf(tc.Map)] as TMap;
        mi := MapInfo.Objects[MapInfo.IndexOf(tm.Name)] as MapTbl;
        tl := tc.Skill[tc.MSkill].Data;

        tc1 := tc.AData;
        xy := tc1.Point;

        for j1 := (xy.Y - tl.Range2) div 8 to (xy.Y + tl.Range2) div 8 do begin
            for i1 := (xy.X - tl.Range2) div 8 to (xy.X + tl.Range2) div 8 do begin
                for k1 := 0 to tm.Block[i1][j1].Mob.Count - 1 do begin
                    ts := tm.Block[i1][j1].Mob.Objects[k1] as TMob;

                    if (rangefield = 1) then begin
                        if (abs(ts.Point.X - xy.X) <= tl.Range) and (abs(ts.Point.Y - xy.Y) <= tl.Range) then sl.AddObject(IntToStr(ts.ID),ts);
                    end else if (rangefield = 2) then begin
                        if (abs(ts.Point.X - xy.X) <= tl.Range2) and (abs(ts.Point.Y - xy.Y) <= tl.Range2) then sl.AddObject(IntToStr(ts.ID),ts);
                    end;
                end;

                for k1 := 0 to tm.Block[i1][j1].CList.Count - 1 do begin
                    if ((tm.Block[i1][j1].CList.Objects[k1] is TChara) = false) then Continue;
                    tc1 := tm.Block[i1][j1].CList.Objects[k1] as TChara;
                    if (tc = tc1) or ((mi.PvPG = true) and (tc.GuildID = tc1.GuildID) and (tc.GuildID <> 0)) then Continue;

                    if (rangefield = 1) then begin
                        if (abs(tc1.Point.X - xy.X) <= tl.Range) and (abs(tc1.Point.Y - xy.Y) <= tl.Range) then sl.AddObject(IntToStr(tc1.ID),tc1);
                    end else if (rangefield = 2) then begin
                        if (abs(tc1.Point.X - xy.X) <= tl.Range2) and (abs(tc1.Point.Y - xy.Y) <= tl.Range2) then sl.AddObject(IntToStr(tc1.ID),tc1);
                    end;
                end;
            end;
        end;

        Result := sl;
    end;

    function check_allow_pvp(tc : TChara) : Boolean;
    var
    	mi : MapTbl;
    begin
    	mi := MapInfo.Objects[MapInfo.IndexOf(tc.Map)] as MapTbl;

        if (not mi.PvP) and (tc.MTargetType <> 0) then Result := False
        else Result := True;
    end;


    { -------------------------------------------------- }
    { - Job: Swordsman --------------------------------- }
    { - Job ID: 1 -------------------------------------- }
    { - Skill Name: Sword Mastery ---------------------- }
    { - Skill ID Name: SM_SWORD ------------------------ }
    { - Skill ID: 2 ------------------------------------ }
    { -------------------------------------------------- }
    function skill_sword_mastery(tc : TChara) : Integer;
    begin
        if ( (tc.WeaponType[0] = 1) or (tc.WeaponType[0] = 2) ) then begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -