なので、例えば、
until ((tm.gat[xy.X][xy.Y] and 1) <> 0) or (c = 100);
↑のようなgatのメモリを参照する式の手前で、
if (xy.X < 0) then beginxy.X := 0;end;
if (xy.Y < 0) then beginxy.Y := 0;end;
if (xy.X > tm.Size.X-1) then beginxy.X := tm.Size.X-1;end;
if (xy.Y > tm.Size.Y-1) then beginxy.Y := tm.Size.Y-1;end;
のような式を書いてやればエラー落ちしなくまりました。
私は、4376、4427、4599、4640、4645行目に修正を加えてあります。
xy.Xではなく、Point.Xなどとなっている場合もあるので適宜変更してください。
1: //sell
begin
w := 0;
for i := 1 to 100 do begin
if (tc.Item[i].Amount > 0) and (tc.Item[i].ID <> 0) then begin
w := w + 1;
end;
end;
WFIFOW(0, $00c7);
WFIFOW(2, 4 + w * 10);
j := 0;
for i := 1 to 100 do begin
if (tc.Item[i].Amount > 0) and (tc.Item[i].ID <> 0) then begin
j := j + 1;
WFIFOW(4 + (j-1)*10,j);
WFIFOL(6 + (j-1)*10,tc.Item[i].Data.Price);
WFIFOL(10+ (j-1)*10,tc.Item[i].Data.Price);//OC未対応
end;
end;
Socket.SendBuf(buf, 4 + w * 10);
end;
とやってみました まだ売るとこはつくってないんですが
Sell押したときに表示はされるとおもいます
なにぶんDelphiを始めて5日目なのでご指摘お願いします(;´д`)
WFIFOW(0, $00c7);
w := 0;
for i := 1 to 100 do begin
if (tc.Item[i].Amount > 0) and (tc.Item[i].ID <> 0) and (tc.Item[i].Equip = 0) then begin
WFIFOW( 4+ w*10, i);
WFIFOL( 6+ w*10, tc.Item[i].Data.Price div 2);
WFIFOL(10+ w*10, tc.Item[i].Data.Price div 2);//OC未対応
Inc(w);
end;
end;
WFIFOW(2, 4 + w * 10);
Socket.SendBuf(buf, 4 + w * 10);
k := 250 - Param[1] - (Param[4] div 4);
if (250 - Param[1] - (Param[4] div 4)) < 1 then begin
k := 1;
end else begin
k := 250 - Param[1] -(Param[4] div 4);
end;
ADelay := 20 * WeaponASPDTable[Job][WeaponType] * k div 250;
if ADelay < 200 then ADelay := 200;
if (BaseLV + Param[2]) > 203 then begin
HPDelay[0] := 150;
end else begin
HPDelay[0] := 3000 - (14 * (BaseLV + Param[2]));
end;
これで多分ダイジョウブかと
さらにクリティカルの実装
攻撃処理の直前に以下を挿入
l := integer(Critical);
atk_type := 0;
//Critical処理
if Random(100) < l then begin
if Weapon = 0 then begin
//素手
dmg[0] := ATK3;
end else begin
//素手以外
dmg[0] := ATK3 + (ATK * WeaponTypeTable[ts.Data.Scale][Weapon] div 100);
end;
atk_type := 10;
end else begin
〜省略〜
end
〜省略〜
WFIFOB(26。�ョ atk_type);
HPRTickをHPTickと同様に初期化しておく
var SM_RECOVERY:byte; //SM_RECOVERYの有無
SM_RECOVERY_LV:byte;//SM_RECOVERYのレベル
if SM_RECOVERY = 1 then begin
if HPRTick + 10000 <= Tick then begin
if HP <> MAXHP then begin
HPR := (SM_RECOVERY_LV * 5) + (MAXHP div 50);
if HP + HPR > MAXHP then HPR := MAXHP - HP;
HP := HP + HPR;
HPRTick := HPRTick + 10000;
WFIFOW( 0。�ョ $013d);
WFIFOW( 2。�ョ $0005);
WFIFOW( 4。�ョ HPR);
Socket.SendBuf(buf。�ョ 6);
end else begin
HPRTick := Tick;
end;
end;
end;
>>6
ASPDは、
i := Param[1] + (Param[4] div 4);
if i > 250 then i := 250;
ADelay := 20 * WeaponASPDTable[Job][WeaponType] * (250 - i) div 250;
if ADelay < 200 then Adelay := 200;
こんな感じにしました。
VITが高すぎるときにHP回復しない問題については、
そのままコピペさせていただきました。<(_ _)>
INTのも同様な処理を追加。
ダブルアタックはクリティカルより優先。
クリティカルはヒットより優先。
ってことで修正案作って見ました。
〜省略〜
if Random(100) < k then begin
miss := False; //命中
end else begin
miss := True; //ミス
end;
if (SkillPer = 0) and ( Random(100) < Critical ) then begin
crt := True;
end else begin
crt := False;
end;
if (SkillPer = 0) and ( Random(100) < DAPer ) then begin
//ダブルアタック
if miss = False then begin
//命中したのなら
dmg[4] := 2;
dmg[5] := 8;
end else begin
//ミス
if crt = True then begin
//クリティカル
miss := False;
dmg[4] := 1;
dmg[5] := 10;
end;
end;
end else begin
//通常攻撃
dmg[4] := 1;
if crt = True then begin
//クリティカル
miss := False;
dmg[5] := 10;
end else begin
//通常攻撃
dmg[5] := 0;
end;
end;
if miss = False then begin
〜省略〜
if not (DisableLevelLimit and (tc1.BaseLV >= 99)) then begin
l := ts.Data.MEXP * BaseExpMultiplier;
if l > tc1.BaseNextEXP then l := tc1.BaseNextEXP;
tc1.BaseEXP := tc1.BaseEXP + l;
end;
end else if Copy(str, 1, 7) = 'option ' then begin
if Copy(str, 8, 4) = 'peko' then begin
if tc.job = 7 then begin
WFIFOW(0, $0119);
WFIFOL(2, tc.PID);
WFIFOW(6, 0);
WFIFOW(8, 0);
WFIFOW(10, 15);
WFIFOB(12, 0);
Socket.SendBuf(buf, 13);
end;
end;
防具精錬は書く前に実装されたので完全回避の方を。
〜省略〜
if (SkillPer = 0) and (Random(100) < tc.Lucky) then begin
dmg[0] := 0;
dmg[5] := 11;
end else if not miss then begin
〜省略〜
コレをモンスター反撃ダメージ計算の所に入れるだけでOKです。
//--------------------------------------------------------------------------
$017a: //カードWクリック
begin
RFIFOW(2, w);
if (w >= 1) and (w <= 100) then begin
td := tc.Item[w].Data;
WFIFOW(0, $017b);
j := 4;
for i := 1 to 100 do begin
if (tc.Item[i].ID <> 0) and (tc.Item[i].Amount > 0) and (tc.Item[i].Data.Slot > 0 ) and (tc.Item[i].Card[tc.Item[i].Data.Slot - 1] = 0) then begin // スロットを持っていてスロットの最後が埋まってなければ
case td.Loc of
0: //武器
begin
if (tc.Item[i].Data.Loc = 2) or (tc.Item[i].Data.Loc = 34) then begin
WFIFOW(j, i);
j := j + 2;
end;
end;
769: //頭装備
begin
if (tc.Item[i].Data.Loc = 1) or (tc.Item[i].Data.Loc > 256) then begin
WFIFOW(j, i);
j := j + 2;
end;
end;
4,16,32,64,136: //他
begin
if (tc.Item[i].Data.Loc = td.Loc) then begin
WFIFOW(j, i);
j := j + 2;
end;
end;
end;
end;
end;
if j <> 4 then begin //挿入可能なアイテムがある場合
WFIFOW(2, j);
Socket.SendBuf(buf, j);
tc.UseItemID := w;
end;
end;
end;
//--------------------------------------------------------------------------
$017c: //カード挿入
//本来はここでも装着可能部位かチェックしないといけないんですが
//通常の操作ではありえない(WPE等を使ったチートでもなければ)ので割愛
begin
RFIFOW(4, w);
if (w < 1) or (w > 100) or (tc.Item[tc.UseItemID].Data.IType <> 6) or (tc.Item[w].Card[tc.Item[w].Data.Slot - 1] <> 0) then begin
WFIFOW(0, $017d);
WFIFOW(2, w);
WFIFOW(4, tc.UseItemID);
WFIFOB(6, 1);
Socket.SendBuf(buf, 7);
continue;
end;
for i := 0 to 3 do begin
if(tc.Item[w].Card[i] = 0) then begin
tc.Item[w].Card[i] := tc.Item[tc.UseItemID].Data.ID;
WFIFOW(0, $017d);
WFIFOW(2, w);
WFIFOW(4, tc.UseItemID);
WFIFOB(6, 0);
Socket.SendBuf(buf, 7);
break;
end;
end;
//--------------------------------------------------------------------------
$017a: //カードWクリック
begin
RFIFOW(2, w);
if (w >= 1) and (w <= 100) then begin
td := tc.Item[w].Data;
WFIFOW(0, $017b);
j := 4;
for i := 1 to 100 do begin
if (tc.Item[i].ID <> 0) and (tc.Item[i].Amount > 0) and (tc.Item[i].Data.Slot > 0 ) and (tc.Item[i].Card[tc.Item[i].Data.Slot - 1] = 0) and (tc.Item[i].Equip = 0) then begin // スロットを持っていてスロットの最後が埋まってなければ
case td.Loc of
0: //武器
begin
if (tc.Item[i].Data.Loc = 2) or (tc.Item[i].Data.Loc = 34) then begin
WFIFOW(j, i);
j := j + 2;
end;
end;
769: //頭装備
begin
if (tc.Item[i].Data.Loc = 1) or (tc.Item[i].Data.Loc >= 256) then begin
WFIFOW(j, i);
j := j + 2;
end;
end;
4,16,32,64,136: //他
begin
if (tc.Item[i].Data.Loc = td.Loc) then begin
WFIFOW(j, i);
j := j + 2;
end;
end;
end;
end;
end;
if j <> 4 then begin //挿入可能なアイテムがある場合
WFIFOW(2, j);
Socket.SendBuf(buf, j);
tc.UseItemID := w;
end;
end;
end;
//--------------------------------------------------------------------------
$017c: //カード挿入
//本来はここでも装着可能部位かチェックしないといけないんですが
//通常の操作ではありえない(WPE等を使ったチートでもなければ)ので割愛
begin
RFIFOW(4, w);
if (w < 1) or (w > 100) or (tc.Item[tc.UseItemID].Data.IType <> 6) or (tc.Item[w].Card[tc.Item[w].Data.Slot - 1] <> 0) or (tc.Item[w].Equip <> 0) then begin
WFIFOW(0, $017d);
WFIFOW(2, w);
WFIFOW(4, tc.UseItemID);
WFIFOB(6, 1);
Socket.SendBuf(buf, 7);
continue;
end;
for i := 0 to 3 do begin
if(tc.Item[w].Card[i] = 0) then begin
tc.Item[w].Card[i] := tc.Item[tc.UseItemID].Data.ID;
WFIFOW(0, $017d);
WFIFOW(2, w);
WFIFOW(4, tc.UseItemID);
WFIFOB(6, 0);
Socket.SendBuf(buf, 7);
break;
end;
end;