X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_weapons.pas;h=d9c20e62c7711a3c7c4faf1a12aac97afabd07a3;hb=4e759d19749e8de5b7d1c8e8ca94a46cbabefae0;hp=f8028eef33fc30d94871d95b80759ae45421593c;hpb=829537fc7b2b29baaab7287e54fba2cdd8d00b5c;p=d2df-sdl.git diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index f8028ee..d9c20e6 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -119,7 +119,7 @@ const implementation uses - Math, g_map, g_player, g_gfx, g_sound, g_main, + Math, g_map, g_player, g_gfx, g_sound, g_main, g_panel, g_console, SysUtils, g_options, g_game, g_triggers, MAPDEF, e_log, g_monsters, g_saveload, g_language, g_netmsg; @@ -243,69 +243,97 @@ begin WaterArray := nil; end; -procedure CheckTrap(ID: DWORD; dm: Integer; t: Byte); var - a, b, c, d, i1, i2: Integer; - pl, mn: WArray; + chkTrap_pl: array [0..256] of Integer; + chkTrap_mn: array [0..65535] of TMonster; - function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean; +procedure CheckTrap(ID: DWORD; dm: Integer; t: Byte); +var + //a, b, c, d, i1, i2: Integer; + //chkTrap_pl, chkTrap_mn: WArray; + plaCount: Integer = 0; + mnaCount: Integer = 0; + frameId: DWord; + + { + function monsWaterCheck (mon: TMonster): Boolean; begin result := false; // don't stop - if mon.Live and mon.Collide(gWater[WaterMap[a][c]]) and (not InWArray(monidx, mn)) and (i2 < 1023) then //FIXME + if mon.Live and mon.Collide(gWater[WaterMap[a][c]]) and (not InWArray(monidx, chkTrap_mn)) and (i2 < 1023) then //FIXME begin i2 += 1; - mn[i2] := monidx; + chkTrap_mn[i2] := monidx; end; end; + } + function monsWaterCheck (mon: TMonster): Boolean; + begin + result := false; // don't stop + if (mon.trapCheckFrameId <> frameId) then + begin + mon.trapCheckFrameId := frameId; + chkTrap_mn[mnaCount] := mon; + Inc(mnaCount); + end; + end; + +var + a, b, c, d, f: Integer; + pan: TPanel; begin if (gWater = nil) or (WaterMap = nil) then Exit; - i1 := -1; - i2 := -1; + frameId := g_Mons_getNewTrapFrameId(); + + //i1 := -1; + //i2 := -1; - SetLength(pl, 1024); - SetLength(mn, 1024); - for d := 0 to 1023 do pl[d] := $FFFF; - for d := 0 to 1023 do mn[d] := $FFFF; + //SetLength(chkTrap_pl, 1024); + //SetLength(chkTrap_mn, 1024); + //for d := 0 to 1023 do chkTrap_pl[d] := $FFFF; + //for d := 0 to 1023 do chkTrap_mn[d] := $FFFF; for a := 0 to High(WaterMap) do + begin for b := 0 to High(WaterMap[a]) do begin - if not g_Obj_Collide(gWater[WaterMap[a][b]].X, gWater[WaterMap[a][b]].Y, - gWater[WaterMap[a][b]].Width, gWater[WaterMap[a][b]].Height, - @Shots[ID].Obj) then Continue; + pan := gWater[WaterMap[a][b]]; + if not g_Obj_Collide(pan.X, pan.Y, pan.Width, pan.Height, @Shots[ID].Obj) then continue; for c := 0 to High(WaterMap[a]) do begin - if gPlayers <> nil then + pan := gWater[WaterMap[a][c]]; + for d := 0 to High(gPlayers) do begin - for d := 0 to High(gPlayers) do - if (gPlayers[d] <> nil) and (gPlayers[d].Live) then - if gPlayers[d].Collide(gWater[WaterMap[a][c]]) then - if not InWArray(d, pl) then - if i1 < 1023 then - begin - i1 := i1+1; - pl[i1] := d; - end; + if (gPlayers[d] <> nil) and (gPlayers[d].Live) then + begin + if gPlayers[d].Collide(pan) then + begin + f := 0; + while (f < plaCount) and (chkTrap_pl[f] <> d) do Inc(f); + if (f = plaCount) then + begin + chkTrap_pl[plaCount] := d; + Inc(plaCount); + if (plaCount = Length(chkTrap_pl)) then break; + end; + end; + end; end; - g_Mons_ForEach(monsWaterCheck); + //g_Mons_ForEach(monsWaterCheck); + g_Mons_ForEachAliveAt(pan.X, pan.Y, pan.Width, pan.Height, monsWaterCheck); end; - if i1 <> -1 then - for d := 0 to i1 do - gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t); - - if i2 <> -1 then - for d := 0 to i2 do - g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t); + for f := 0 to plaCount-1 do gPlayers[chkTrap_pl[f]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t); + for f := 0 to mnaCount-1 do chkTrap_mn[f].Damage(dm, 0, 0, Shots[ID].SpawnerUID, t); end; + end; - pl := nil; - mn := nil; + //chkTrap_pl := nil; + //chkTrap_mn := nil; end; function HitMonster(m: TMonster; d: Integer; vx, vy: Integer; SpawnerUID: Word; t: Byte): Boolean; @@ -318,9 +346,9 @@ begin tt := g_GetUIDType(SpawnerUID); if tt = UID_MONSTER then begin - mon := g_Monsters_Get(SpawnerUID); + mon := g_Monsters_ByUID(SpawnerUID); if mon <> nil then - mt := g_Monsters_Get(SpawnerUID).MonsterType + mt := g_Monsters_ByUID(SpawnerUID).MonsterType else mt := 0; end @@ -392,7 +420,7 @@ end; function GunHit(X, Y: Integer; vx, vy: Integer; dmg: Integer; SpawnerUID: Word; AllowPush: Boolean): Byte; - {function monsCheck (monidx: Integer; mon: TMonster): Boolean; + {function monsCheck (mon: TMonster): Boolean; begin result := false; // don't stop if mon.Live and mon.Collide(X, Y) then @@ -405,7 +433,7 @@ function GunHit(X, Y: Integer; vx, vy: Integer; dmg: Integer; end; end;} - function monsCheck (monidx: Integer; mon: TMonster): Boolean; + function monsCheck (mon: TMonster): Boolean; begin result := false; // don't stop if HitMonster(mon, dmg, vx*10, vy*10-3, SpawnerUID, HIT_SOME) then @@ -434,15 +462,15 @@ begin if Result <> 0 then Exit; //if g_Mons_ForEach(monsCheck) then result := 2; - if g_Mons_ForEachAtAlive(X, Y, 1, 1, monsCheck) then result := 2; + if g_Mons_ForEachAliveAt(X, Y, 1, 1, monsCheck) then result := 2; end; procedure g_Weapon_BFG9000(X, Y: Integer; SpawnerUID: Word); - function monsCheck (monidx: Integer; mon: TMonster): Boolean; + function monsCheck (mon: TMonster): Boolean; begin result := false; // don't stop - if (mon <> nil) and (mon.Live) and (mon.UID <> SpawnerUID) then + if (mon.Live) and (mon.UID <> SpawnerUID) then begin with mon do begin @@ -505,7 +533,8 @@ begin gPlayers[i].BFGHit(); end; - g_Mons_ForEach(monsCheck); + //FIXME + g_Mons_ForEachAlive(monsCheck); end; function g_Weapon_CreateShot(I: Integer; ShotType: Byte; Spawner, TargetUID: Word; X, Y, XV, YV: Integer): LongWord; @@ -766,10 +795,11 @@ var end; end; + { function monsCheckHit (monidx: Integer; mon: TMonster): Boolean; begin result := false; // don't stop - if (mon <> nil) and mon.Live and g_Obj_Collide(obj, @mon.Obj) then + if mon.Live and g_Obj_Collide(obj, @mon.Obj) then begin if HitMonster(mon, d, obj^.Vel.X, obj^.Vel.Y, SpawnerUID, t) then begin @@ -782,10 +812,27 @@ var end; end; end; + } + + function monsCheckHit (mon: TMonster): Boolean; + begin + result := false; // don't stop + if HitMonster(mon, d, obj.Vel.X, obj.Vel.Y, SpawnerUID, t) then + begin + if (t <> HIT_FLAME) then + begin + mon.Push((obj.Vel.X+obj.Accel.X)*IfThen(t = HIT_BFG, 8, 1) div 4, + (obj.Vel.Y+obj.Accel.Y)*IfThen(t = HIT_BFG, 8, 1) div 4); + end; + result := true; + end; + end; function MonsterHit(): Boolean; begin - result := g_Mons_ForEach(monsCheckHit); + //result := g_Mons_ForEach(monsCheckHit); + //FIXME: accelerate this! + result := g_Mons_ForEachAliveAt(obj.X+obj.Rect.X, obj.Y+obj.Rect.Y, obj.Rect.Width, obj.Rect.Height, monsCheckHit); end; begin @@ -876,43 +923,41 @@ begin case g_GetUIDType(UID) of UID_PLAYER: Result := HitPlayer(g_Player_Get(UID), d, 0, 0, SpawnerUID, t); - UID_MONSTER: Result := HitMonster(g_Monsters_Get(UID), d, 0, 0, SpawnerUID, t); + UID_MONSTER: Result := HitMonster(g_Monsters_ByUID(UID), d, 0, 0, SpawnerUID, t); else Exit; end; end; function g_Weapon_Explode(X, Y: Integer; rad: Integer; SpawnerUID: Word): Boolean; var - r: Integer; + r: Integer; // squared radius - function monsExCheck (monidx: Integer; mon: TMonster): Boolean; + function monsExCheck (mon: TMonster): Boolean; var dx, dy, mm: Integer; begin result := false; // don't stop - if mon <> nil then begin - with mon do - begin - dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X; - dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y; + dx := mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-X; + dy := mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-Y; - if dx > 1000 then dx := 1000; - if dy > 1000 then dy := 1000; + if dx > 1000 then dx := 1000; + if dy > 1000 then dy := 1000; - if (dx*dx+dy*dy < r) then - begin - //m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y, Obj.Rect.Width, Obj.Rect.Height); - - mm := Max(abs(dx), abs(dy)); - if mm = 0 then mm := 1; + if (dx*dx+dy*dy < r) then + begin + //m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y, Obj.Rect.Width, Obj.Rect.Height); + //e_WriteLog(Format('explo monster #%d: x=%d; y=%d; rad=%d; dx=%d; dy=%d', [monidx, X, Y, rad, dx, dy]), MSG_NOTIFY); - if mon.Live then - HitMonster(mon, ((mon.Obj.Rect.Width div 4)*10*(rad-mm)) div rad, - 0, 0, SpawnerUID, HIT_ROCKET); + mm := Max(abs(dx), abs(dy)); + if mm = 0 then mm := 1; - mon.Push((dx*7) div mm, (dy*7) div mm); + if mon.Live then + begin + HitMonster(mon, ((mon.Obj.Rect.Width div 4)*10*(rad-mm)) div rad, 0, 0, SpawnerUID, HIT_ROCKET); end; + + mon.Push((dx*7) div mm, (dy*7) div mm); end; end; end; @@ -920,9 +965,8 @@ var var i, h, dx, dy, m, mm: Integer; _angle: SmallInt; - begin - Result := False; + result := false; g_Triggers_PressC(X, Y, rad, SpawnerUID, ACTIVATE_SHOT); @@ -954,8 +998,8 @@ begin end; end; - g_Mons_ForEach(monsExCheck); - + //g_Mons_ForEach(monsExCheck); + g_Mons_ForEachAt(X-(rad+32), Y-(rad+32), (rad+32)*2, (rad+32)*2, monsExCheck); h := High(gCorpses);