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

📄 skills.pas

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

(*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
Skills
2004/05/31 ChrstphrR
(Original code moved from Main, and other units, from various coders from
Weiss, EWeiss, Fusion.
I won't dare take credit for anything but reorganizing things so they're
saner to look at.)

--
Overview:
--
Routines that affect skills needed a proper home ... Main.pas should REALLY just
be code that affects some of the startup, shutdown, and Form events.  Separating
out some of this code from it will make tracking down both types of routines
easier.

--
Revisions:
--
v0.1 2004/05/31
2004/05/31 [ChrstphrR] - Initial Unit creation
"/05/31 [ChrstphrR] - Import of SkillEffect
"/06/02 [DarkHelmet] - Reorder case statements numerically (partially done)
"/06/02 [DarkHelmet] - CODE-ERROR comments added for future fixes
"/06/03 [ChrstphrR] - Added link to Skill_Constants.pas
"/06/03 [ChrstphrR] - Added FindTargetsInAttackRange to replace some of the
	code that DH mentioned - will evolve into a more general routine.
"/06/03 [ChrstphrR] - Some Memory leak fixes in SkillEffect
"/06/03 [Darkhelmet] - Organized all except the platinum skills in player vs monster


*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*)

interface

uses
	{Delphi VCL Units}
	Windows, Classes,
	{Fusion Units}
	Common, Skill_Constants, Player_Skills, Globals,
	{3rd Party Units}
	List32;

	Procedure SkillEffect(
			tc   : TChara;
			Tick : Cardinal;
            UseSP : Boolean = True
		);

	Procedure FindTargetsInAttackRange(
			TrgtList  : TIntList32;
			SData     : TSkillDB;
			Chara     : TChara;
			TrgtPt    : TPoint;
			Target    : TLiving; //May be NIL
			TargetChk : Byte
		);

const
	//TargetChk Constants for FindTargetsInAttackRange()
	CHK_NONE   = 0; // No Other Checks Needed
	CHK_SELF   = 1; // Ensure TargetList doesn't include Chara
	CHK_TARGET = 2; // Ensure TargetList doesn't include Primary Target
	CHK_GUARD  = 3; // Ensure TargetList doesn't include GuildGuardians
	CHK_GUILD  = 4; // Ensure TargetList doesn't include GuildMembers

implementation

uses
	SysUtils,
	Main, Path;


(*-----------------------------------------------------------------------------*
SkillEffect()

Overview:
	Erm... I just imported it! >.< ... it's nearly 6000 lines long, gimme a break!
	I mean... an overview of what this routine does will be forthcoming.

	This is a Weiss era routine.

	Plan of attack for changes:
	- Import into new unit to reduce clutter in Main.Pas (and DL time from CVS)
	- consistantly format using tabs for indents (you can set them to what you
	prefer for your indent style off of the Properties... menu choice when you
	right-click the source.
	- remove variables that are unused outright
	- pick out candidate code to reduce this from a 6000 line function to a few
	hundred lines.  This unit WILL be refactored.

Pre:
	Unknown
Post:
	Unknown

Revisions:
2004/04/27 [ChrstphrR] Memory Leak Fixes
"/05/31 [ChrstphrR] Imported into Skills unit from Main.pas
"/06/02 [DarkHelmet] CODE-ERROR comments where further work is needed
"/06/02 [DarkHelmet] Partial reorder of case statements by number --
	Skills grouped and marked by Job (Swordsman, Mage, Thief, etc)
*-----------------------------------------------------------------------------*)
Procedure SkillEffect(
		tc   : TChara;
		Tick : Cardinal;
        UseSP : Boolean = True
	);
Var
	j,k,m,b         : Integer;
	i               : Integer;
	L               : integer;
	i1,j1,k1        :integer;
	tm              :TMap;
	mi              :MapTbl;
	tc1             :TChara;
	tc2             :TChara;
	ts              :TMob;
	ts1             :TMob;
  td              :TItemDB;
  tg              :TGuild;
	tl              :TSkillDB;
	xy              :TPoint;
	bb              :array of byte;
	tpa             :TParty;
	sl              :TStringList;
  ma              :TMArrowDB;
  tma             :TMaterialDB;
  ProcessType     :Byte;
  DamageProcessed :boolean;
	tn :TNPC;

	//CR - 2004/06/03
	MonsterList : TIntList32;
	//Used to store list of Monsters in an area skill (i.e. splash damage)


Begin
	// Alex: This should not be preset. Depending on certain skill failure
	// such as I encountered with "Steal" this will cause the skill effect
	// to go through even when the skill fails.  I'm not sure which skills need
	// this, but it should be declared in the skill section, not out here.
	ProcessType := 99;

	if tc.Skill[269].Tick > Tick then begin  //Check if BladeStop is active
		case tc.Skill[269].Effect1 of
		1: Exit;
		2: if tc.MSkill <> 267 then exit;
		3: if ((tc.MSkill <> 267) and (tc.MSkill <> 266)) then exit;
		4: if ((tc.MSkill <> 267) and (tc.MSkill <> 266) and (tc.MSkill <> 273)) then exit;
		5: if ((tc.MSkill <> 267) and (tc.MSkill <> 266) and (tc.MSkill <> 273) and (tc.MSkill <> 271)) then exit;
		end;//case -- all exits here are safe 2004/04/27
	end;
	if tc.isSilenced then begin
		SilenceCharacter(tm, tc, Tick);
		Exit;//safe 2004/04/27
	end;

	{ChrstphrR 2004/04/26 -- moved this away from the first Exit calls.}
	sl := TStringList.Create;

	with tc do begin
    //Set the map data From the players map data
		tm := MData;

		tL := Skill[MSkill].Data;

    if Mapinfo.IndexOf(tm.Name) <> -1 then
	  	mi := MapInfo.Objects[MapInfo.IndexOf(tm.Name)] as MapTbl
    else exit;  //safe exit if map isn't found in mapinfo

    	{ Alex: Holy Shit, here we go. This needs to be
        called before any tests for target type are made
        the reason being that one skill function should
        be used for both types of targets.
        - Placed here after all declarations for safety. }
        parse_skills(tc, Tick, 0, UseSP);

		if MTargetType = 0 then begin //Target is a monster
			ts := tc.AData;

			if tL = NIL then begin
				sl.Free;
				Exit;//safe 2004/04/26
			end;

			if (ts is TMob) and (PassiveAttack = false) then begin // Edited by AlexKreuz
				if ts.isEmperium then begin
					j := GuildList.IndexOf(tc.GuildID);
					if (j <> -1) then begin
						tg := GuildList.Objects[j] as TGuild;
						if ((tg.GSkill[10000].Lv < 1) or ((ts.GID = tc.GuildID) and (tc.GuildID <> 0))) then begin
							MSkill := 0;
							MUseLv := 0;
							MMode := 0;
							MTarget := 0;
							sl.Free;
							Exit;//safe 2004/04/26
						end;
					end;
				end;

				if ((ts.isGuardian = tc.GuildID) and (tc.GuildID <> 0)) then begin //added by The Harbinger -- darkWeiss version
					MSkill := 0;
					MUseLv := 0;
					MMode := 0;
					MTarget := 0;
					sl.Free;
					Exit;//safe 2004/04/26
				end;
			end;

			if (ts = nil) or (ts.HP = 0) and (PassiveAttack = False) then begin
				MSkill := 0;
				MUseLv := 0;
				MMode := 0;
				MTarget := 0;
				sl.Free;
				Exit;//safe 2004/04/26
			end;

			//If Monster is in range of the skill
if (abs(tc.Point.X - ts.Point.X) <= tl.Range) and (abs(tc.Point.Y - ts.Point.Y) <= tl.Range) then begin

				case MSkill of  {Skill Used Against Monster}

				//June 02, 2004 - Darkhelmet, I'm going to begin cleaning and organizing all these skills,
				//wish me luck!
                                      	                        8: //僀儞僨儏傾
					begin
						tc1 := tc;
						ProcessType := 2;
					end;
				{Mage Skills Player vs Monster Begin}
				15:     {Frost Driver}
					begin
						//Magic Attack Damage Calculation
						dmg[0] := MATK1 + Random(MATK2 - MATK1 + 1) * MATKFix div 100 * ( MUseLV + 100 ) div 100;
						dmg[0] := dmg[0] * (100 - ts.Data.MDEF) div 100; //MDEF%
						dmg[0] := dmg[0] - ts.Data.Param[3]; //MDEF-
						if dmg[0] < 1 then
							dmg[0] := 1;
						dmg[0] := dmg[0] * ElementTable[tl.Element][ts.Element] div 100;
						if dmg[0] < 0 then
							dmg[0] := 0; //杺朄峌寕偱偺夞暅偼枹幚憰

						if (ts.EffectTick[0] > Tick) then dmg[0] := dmg[0] * 2;
						//Send Attacking Packets
						SendCSkillAtk1(tm, tc, ts, Tick, dmg[0], 1);

						//Freezing Chance
						if (ts.Data.race <> 1) and (ts.Data.MEXP = 0) and (dmg[0] <> 0)then begin
							if Random(1000) < tl.Data1[MUseLV] * 10 then begin
								ts.nStat := 2;
								ts.BodyTick := Tick + tc.aMotion;
							end;
						end;
						frmMain.DamageProcess1(tm, tc, ts, dmg[0], Tick, False);
						tc.MTick := Tick + 1500;
					end;

				16:     {Stone Curse}
					begin
						j := SearchCInventory(tc, 716, false);
						if ((j <> 0) and (tc.Item[j].Amount >= 1)) or (NoJamstone) then begin

							//Use the Item
							if NOT NoJamstone then begin
								UseItem(tc, j);
							end;

							//Send Graphic Packet
							WFIFOW( 0, $011a);
							WFIFOW( 2, MSkill);
							WFIFOW( 4, dmg[0]);
							WFIFOL( 6, MTarget);
							WFIFOL(10, ID);
							WFIFOB(14, 1);
							SendBCmd(tm, ts.Point, 15);
							if Random(1000) < tl.Data1[MUseLV] * 10 then begin
								if (ts.Stat1 <> 1) then begin
									ts.nStat := 1;
									ts.BodyTick := Tick + tc.aMotion;
								end;
							end;
						end else begin
							SendSkillError(tc, 7); //No Red Gemstone
							tc.MMode := 4;
							tc.MPoint.X := 0;
							tc.MPoint.Y := 0;
							Exit;
						end;
					end;

				MG_FIREBALL: //17 Fire Ball
					begin
						//XY is the targeting point.
						xy := ts.Point;
						MonsterList := TIntList32.Create;
						try
							FindTargetsInAttackRange(MonsterList,tl,tc,xy,ts,CHK_NONE);

							if MonsterList.Count > 0 then begin
								//For each monster, calculate damage inflicted.
								for k1 := 0 to MonsterList.Count -1 do begin
									ts1 := MonsterList.Objects[k1] AS TMob;
									dmg[0] := MATK1 + Random(MATK2 - MATK1 + 1) * MATKFix div 100 * tl.Data1[MUseLV] div 100;
									dmg[0] := dmg[0] * (100 - ts1.Data.MDEF) div 100; //MDEF%
									dmg[0] := dmg[0] - ts1.Data.Param[3]; //Account for monsters MDEF
									if dmg[0] < 1 then dmg[0] := 1;
									dmg[0] := dmg[0] * ElementTable[tl.Element][ts1.Element] div 100;
									dmg[0] := dmg[0] * tl.Data2[MUseLV];

									if dmg[0] < 0 then dmg[0] := 0; //Prevent negative damage
									if (ts1.EffectTick[0] > Tick) then dmg[0] := dmg[0] * 2;
									if ts = ts1 then begin
										k := 0;
									end else begin
										k := 5;
									end;
									//Send Attack Packets
									SendCSkillAtk1(tm, tc, ts1, Tick, dmg[0], tl.Data2[MUseLV], k);
									//Damage the monster
									frmMain.DamageProcess1(tm, tc, ts1, dmg[0], Tick);
								end;
							end;
						finally
							MonsterList.Free;
						end;
						tc.MTick := Tick + 1600;
					end;//17 MG_FIREBALL
				{Mage Skills Player vs Monster end}

				{Alcolyte Skills Player vs monster begin}
				28:     {Heal}
					begin
						if (ts.HP > 0) then begin

							//Check If Undead
							if (ts.Data.Race = 1) or (ts.Element mod 20 = 9) then begin
								//Damage Calculation
								dmg[0] := ((BaseLV + Param[3]) div 8) * tl.Data1[MUseLV] * ElementTable[6][ts.Element] div 200;

								if dmg[0] < 0 then dmg[0] := 0; //杺朄峌寕偱偺夞暅偼枹幚憰
								if (ts.EffectTick[0] > Tick) then dmg[0] := dmg[0] * 2;
								SendCSkillAtk1(tm, tc, ts, Tick, dmg[0], 1);
								frmMain.DamageProcess1(tm, tc, ts, dmg[0], Tick);

⌨️ 快捷键说明

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