📄 player_skills.pas
字号:
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 + -