X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_player.pas;h=ca23ce315cc7f2009d858a527d208163a0693b47;hb=c146ab01667396f6b030e131e05cb6ce90aaff04;hp=736d22e1623ce2d1291825a49386cc63a75963c9;hpb=4df4eb483aa0a0abd74164d7f49c173743f6c84b;p=d2df-sdl.git diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 736d22e..ca23ce3 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -231,6 +231,8 @@ type procedure doDamage (v: Integer); + function followCorpse(): Boolean; + public FDamageBuffer: Integer; @@ -463,7 +465,7 @@ type PGib = ^TGib; TGib = record - alive: Boolean; + alive: Boolean; ID: DWORD; MaskID: DWORD; RAngle: Integer; @@ -501,6 +503,7 @@ type FDamage: Byte; FColor: TRGB; FObj: TObj; + FPlayerUID: Word; FAnimation: TAnimation; FAnimationMask: TAnimation; @@ -1539,6 +1542,7 @@ begin gCorpses[find_id].FColor := FModel.Color; gCorpses[find_id].FObj.Vel := FObj.Vel; gCorpses[find_id].FObj.Accel := FObj.Accel; + gCorpses[find_id].FPlayerUID := FUID; end else g_Player_CreateGibs(FObj.X + PLAYER_RECT_CX, @@ -3552,34 +3556,81 @@ function TPlayer.getNextWeaponIndex (): Byte; var i: Word; wantThisWeapon: array[0..64] of Boolean; + weaponOrder: array[0..64] of Integer; // value: index in `FWeapon` wwc: Integer = 0; //HACK! - dir, cwi: Integer; + dir, cwi, rwidx, curlidx: Integer; + + function real2log (ridx: Integer): Integer; + var + f: Integer; + begin + if (ridx >= 0) then + begin + for f := 0 to 10 do if (weaponOrder[f] = ridx) then begin result := f; exit; end; + end; + result := -1; + end; + begin result := 255; // default result: "no switch" + // had weapon cycling on previous frame? remove that flag if (FNextWeap and $2000) <> 0 then begin FNextWeap := FNextWeap and $1FFF; FNextWeapDelay := 0; end; + + // build weapon order (k8: i know, i know, learn how to do constants and such... gtfo, please!) + // priorities: + // bfg, plasma, flamethrower, ssg, minigun, sg, pistol, berserk, chainsaw, fist + weaponOrder[0] := WEAPON_BFG; + weaponOrder[1] := WEAPON_PLASMA; + weaponOrder[2] := WEAPON_FLAMETHROWER; + weaponOrder[3] := WEAPON_SHOTGUN2; + weaponOrder[4] := WEAPON_CHAINGUN; + weaponOrder[5] := WEAPON_SHOTGUN1; + weaponOrder[6] := WEAPON_PISTOL; + weaponOrder[7] := WEAPON_KASTET; + weaponOrder[8] := WEAPON_SAW; + weaponOrder[9] := WEAPON_KASTET; + weaponOrder[10] := WEAPON_SUPERPULEMET; + + if (R_BERSERK in FRulez) then weaponOrder[9] := -1 else weaponOrder[7] := -1; + + (* + WEAPON_KASTET = 0; + WEAPON_SAW = 1; + WEAPON_PISTOL = 2; + WEAPON_SHOTGUN1 = 3; + WEAPON_SHOTGUN2 = 4; + WEAPON_CHAINGUN = 5; + WEAPON_ROCKETLAUNCHER = 6; + WEAPON_PLASMA = 7; + WEAPON_BFG = 8; + WEAPON_SUPERPULEMET = 9; + WEAPON_FLAMETHROWER = 10; + *) + // cycling has priority if (FNextWeap and $C000) <> 0 then begin - if (FNextWeap and $8000) <> 0 then - dir := 1 - else - dir := -1; + if (FNextWeap and $8000) <> 0 then dir := 1 else dir := -1; // should be reversed if we want "priority-driven cycling" FNextWeap := FNextWeap or $2000; // we need this - if FNextWeapDelay > 0 then - exit; // cooldown time + if FNextWeapDelay > 0 then exit; // cooldown time + //cwi := real2log(FCurrWeap); + //if (cwi < 0) then cwi := 0; cwi := FCurrWeap; for i := 0 to High(FWeapon) do begin cwi := (cwi+length(FWeapon)+dir) mod length(FWeapon); - if FWeapon[cwi] then + //rwidx := weaponOrder[cwi]; + rwidx := cwi; // sorry + if (rwidx < 0) then continue; + if FWeapon[rwidx] then begin - //e_WriteLog(Format(' SWITCH: cur=%d; new=%d', [FCurrWeap, cwi]), MSG_WARNING); - result := Byte(cwi); + //e_WriteLog(Format(' SWITCH: cur=%d; new=%d (dir=%d; log=%d)', [FCurrWeap, rwidx, dir, cwi]), TMsgType.Warning); + result := Byte(rwidx); FNextWeapDelay := 10; exit; end; @@ -3587,48 +3638,66 @@ begin resetWeaponQueue(); exit; end; + // no cycling - for i := 0 to High(wantThisWeapon) do - wantThisWeapon[i] := false; + for i := 0 to High(wantThisWeapon) do wantThisWeapon[i] := false; for i := 0 to High(FWeapon) do + begin if (FNextWeap and (1 shl i)) <> 0 then begin - wantThisWeapon[i] := true; + cwi := real2log(i); + if (cwi >= 0) then wantThisWeapon[cwi] := true; Inc(wwc); end; - // exclude currently selected weapon from the set - wantThisWeapon[FCurrWeap] := false; + end; + // slow down alterations a little - if wwc > 1 then + if (wwc > 1) then begin //e_WriteLog(Format(' FNextWeap=%x; delay=%d', [FNextWeap, FNextWeapDelay]), MSG_WARNING); - // more than one weapon requested, assume "alteration" and check alteration delay + // more than one weapon requested, assume "alteration", and check alteration delay if FNextWeapDelay > 0 then begin FNextWeap := 0; exit; end; // yeah end; + // do not reset weapon queue, it will be done in `RealizeCurrentWeapon()` // but clear all counters if no weapon should be switched - if wwc < 1 then + if (wwc < 1) then begin resetWeaponQueue(); exit; end; - //e_WriteLog(Format('wwc=%d', [wwc]), MSG_WARNING); - // try weapons in descending order - for i := High(FWeapon) downto 0 do + //e_WriteLog(Format('wwc=%d', [wwc]), TMsgType.Warning); + + // exclude currently selected weapon from the set + curlidx := real2log(FCurrWeap); + //e_WriteLog(Format('FCurrWeap=%d; curlidx=%d', [FCurrWeap, curlidx]), TMsgType.Warning); + //if (curlidx >= 0) then wantThisWeapon[curlidx] := false; + //if (wwc = 2) then begin Dec(wwc); end; // easy case: switch between two weapons + + // find next weapon to switch onto + cwi := curlidx; + for i := 0 to High(FWeapon) do begin - if wantThisWeapon[i] and FWeapon[i] and ((wwc = 1) or hasAmmoForWeapon(i)) then + cwi := (cwi+length(FWeapon)+1) mod length(FWeapon); + if (cwi = curlidx) then continue; // skip current weapon + if not wantThisWeapon[cwi] then continue; + rwidx := weaponOrder[cwi]; + if (rwidx < 0) then continue; + //e_WriteLog(Format(' trying logical %d (real %d)', [cwi, rwidx]), TMsgType.Warning); + if FWeapon[cwi] and ((wwc = 1) or hasAmmoForWeapon(cwi)) then begin // i found her! - result := Byte(i); + result := Byte(rwidx); resetWeaponQueue(); FNextWeapDelay := 10; // anyway, 'cause why not exit; end; end; + // no suitable weapon found, so reset the queue, to avoid accidental "queuing" of weapon w/o ammo resetWeaponQueue(); end; @@ -3659,7 +3728,7 @@ begin if not switchAllowed then begin //HACK for weapon cycling - if (FNextWeap and $7000) <> 0 then FNextWeap := 0; + if (FNextWeap and $E000) <> 0 then FNextWeap := 0; exit; end; @@ -4449,6 +4518,13 @@ begin FRulez := []; end; +// Ðàçðûâàåì ñâÿçè ñ òðóïàìè: + if gCorpses <> nil then + for a := 0 to High(gCorpses) do + if gCorpses[a] <> nil then + if gCorpses[a].FPlayerUID = FUID then + gCorpses[a].FPlayerUID := 0; + // Ïîëó÷àåì êîîðäèíàòû òî÷êè âîçðîæäåíèÿ: if not g_Map_GetPoint(c, RespawnPoint) then begin @@ -4766,6 +4842,30 @@ begin Result := 1; end; +function TPlayer.followCorpse(): Boolean; +var + i: Integer; +begin + Result := False; + if FAlive or FSpectator then + Exit; + if (gCorpses = nil) or (Length(gCorpses) = 0) then + Exit; + for i := 0 to High(gCorpses) do + if gCorpses[i] <> nil then + if gCorpses[i].FPlayerUID = FUID then + begin + Result := True; + FObj.X := gCorpses[i].FObj.X; + FObj.Y := gCorpses[i].FObj.Y; + FObj.Vel.X := gCorpses[i].FObj.Vel.X; + FObj.Vel.Y := gCorpses[i].FObj.Vel.Y; + FObj.Accel.X := gCorpses[i].FObj.Accel.X; + FObj.Accel.Y := gCorpses[i].FObj.Accel.Y; + break; + end; +end; + procedure TPlayer.Update(); var b: Byte; @@ -4842,7 +4942,8 @@ begin if FPhysics then begin - g_Obj_Move(@FObj, True, True, True); + if not followCorpse() then + g_Obj_Move(@FObj, True, True, True); positionChanged(); // this updates spatial accelerators end; @@ -4968,7 +5069,8 @@ begin if FPhysics then begin - g_Obj_Move(@FObj, True, True, True); + if not followCorpse() then + g_Obj_Move(@FObj, True, True, True); positionChanged(); // this updates spatial accelerators end else @@ -6318,6 +6420,7 @@ begin utils.writeInt(st, Byte(FColor.B)); // Îáúåêò òðóïà Obj_SaveState(st, @FObj); + utils.writeInt(st, Word(FPlayerUID)); // Åñòü ëè àíèìàöèÿ anim := (FAnimation <> nil); utils.writeBool(st, anim); @@ -6350,6 +6453,7 @@ begin FColor.B := utils.readByte(st); // Îáúåêò òðóïà Obj_LoadState(@FObj, st); + FPlayerUID := utils.readWord(st); // Åñòü ëè àíèìàöèÿ anim := utils.readBool(st); // Åñëè åñòü - çàãðóæàåì