# HG changeset patch # User Medo # Date 1339365982 -7200 # Node ID 8d04e85ca2041f034269cc6dbdea09e2cfc9317c # Parent 076aba32abd335e515add317cb55af2bcbfe29e8# Parent 9ecd5bc9810b9bc2094595fcfe1e52d9c2050b9e Merge diff -r 076aba32abd3 -r 8d04e85ca204 QTfrontend/game.cpp --- a/QTfrontend/game.cpp Mon Jun 11 00:02:17 2012 +0200 +++ b/QTfrontend/game.cpp Mon Jun 11 00:06:22 2012 +0200 @@ -97,7 +97,7 @@ HWProto::addStringToBuffer(buf, QString("eammprob %1").arg(ammostr.mid(cAmmoNumber, cAmmoNumber))); HWProto::addStringToBuffer(buf, QString("eammdelay %1").arg(ammostr.mid(2 * cAmmoNumber, cAmmoNumber))); HWProto::addStringToBuffer(buf, QString("eammreinf %1").arg(ammostr.mid(3 * cAmmoNumber, cAmmoNumber))); - if(!gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore")); + if(gamecfg->schemeData(15).toBool() || !gamecfg->schemeData(21).toBool()) HWProto::addStringToBuffer(buf, QString("eammstore")); HWProto::addStringListToBuffer(buf, team.teamGameConfig(gamecfg->getInitHealth())); ; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/GSHandlers.inc Mon Jun 11 00:06:22 2012 +0200 @@ -702,14 +702,14 @@ //Land[py, px+1]:= lfBasic; if allpx then - UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w)) + UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w), true) else begin UpdateLandTexture( max(0, min(LAND_WIDTH, xx)), min(LAND_WIDTH - xx, Pred(s^.w)), max(0, min(LAND_WIDTH, yy)), - min(LAND_HEIGHT - yy, Pred(s^.h)) + min(LAND_HEIGHT - yy, Pred(s^.h)), false // could this be true without unnecessarily creating blanks? ); end; ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS //////////////////////////////////// @@ -1025,7 +1025,9 @@ else AmmoShove(Gear, Gear^.Timer, 20); CheckGearDrowning(Gear); - dec(i) until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0); + dec(i) + until (i = 0) or (Gear^.Damage > Gear^.Health) or ((Gear^.State and gstDrowning) <> 0); + if Gear^.Damage > 0 then begin DrawTunnel(oX, oY, Gear^.dX, Gear^.dY, 82 - i, 1); @@ -2077,6 +2079,7 @@ exBoom: boolean; dX, dY: HWFloat; hog: PHedgehog; + sparkles: PVisualGear; begin k := Gear^.Kind; exBoom := false; @@ -2108,6 +2111,21 @@ Gear^.Damage := 0; if Gear^.Health <= 0 then exBoom := true; + end + else + begin + if Gear^.Timer = 0 then + begin +(* Can't make sparkles team coloured without working out what the next team is going to be. This should be solved, really, since it also screws up + voices. Reinforcements voices is heard for active team, not team-to-be. Either that or change crate spawn from end of turn to start, although that + has its own complexities. *) + sparkles:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtDust, 1); + if sparkles <> nil then + begin + sparkles^.Tint:= $FAB22CFF + end + end; + if (GameTicks and $1 = 0) and (Gear^.Timer < 255) then inc(Gear^.Timer) end; if (Gear^.Damage > 0) or exBoom then @@ -3422,7 +3440,7 @@ PlaySound(sndGun); end; - if (Gear^.Timer = 0) or (HHGear^.Damage <> 0) then + if (Gear^.Timer = 0) or ((HHGear^.State and gstHHDriven) = 0) then begin DeleteGear(Gear); AfterAttack diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/SDLh.pas --- a/hedgewars/SDLh.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/SDLh.pas Mon Jun 11 00:06:22 2012 +0200 @@ -270,6 +270,19 @@ AShift = 0; {$ENDIF} + KMOD_NONE = $0000; + KMOD_LSHIFT = $0001; + KMOD_RSHIFT = $0002; + KMOD_LCTRL = $0040; + KMOD_RCTRL = $0080; + KMOD_LALT = $0400; + KMOD_RALT = $0800; + KMOD_LMETA = $0400; + KMOD_RMETA = $0800; + KMOD_NUM = $1000; + KMOD_CAPS = $2000; + KMOD_MODE = $4000; + {* SDL_mixer *} MIX_MAX_VOLUME = 128; MIX_INIT_FLAC = $00000001; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/VGSHandlers.inc --- a/hedgewars/VGSHandlers.inc Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/VGSHandlers.inc Mon Jun 11 00:06:22 2012 +0200 @@ -90,10 +90,16 @@ if round(X) > cRightScreenBorder then X:= X - cScreenSpace; // if round(Y) < (LAND_HEIGHT - 1024 - 75) then Y:= Y + 25.0; // For if flag is set for flakes rising upwards? - if (Gear^.Layer = 2) and (round(Y) - 225 > LAND_HEIGHT) then - Y:= Y - (1024 + 300) // TODO - configure in theme (jellies for example could use limited range) - else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then - Y:= Y - (1024 + 25); + if (Gear^.Layer = 2) and (round(Y) - 225 > LAND_HEIGHT) then + begin + X:= cLeftScreenBorder + random(cScreenSpace); + Y:= Y - (1024 + 250 + random(50)) // TODO - configure in theme (jellies for example could use limited range) + end + else if (Gear^.Layer <> 2) and (round(Y) + 50 > LAND_HEIGHT) then + begin + X:= cLeftScreenBorder + random(cScreenSpace); + Y:= Y - (1024 + random(25)) + end; Timer:= 0; tdX:= 0; tdY:= 0 diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uAI.pas --- a/hedgewars/uAI.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uAI.pas Mon Jun 11 00:06:22 2012 +0200 @@ -111,7 +111,7 @@ procedure TestAmmos(var Actions: TActions; Me: PGear; isMoved: boolean); var BotLevel: Byte; ap: TAttackParams; - Score, i: LongInt; + Score, i, dAngle: LongInt; a, aa: TAmmoType; begin BotLevel:= Me^.Hedgehog^.BotLevel; @@ -129,8 +129,10 @@ ThreadSwitch(); {$ENDIF} repeat - if (CanUseAmmo[a]) and - ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) then + if (CanUseAmmo[a]) + and ((not isMoved) or ((AmmoTests[a].flags and amtest_OnTurn) = 0)) + and ((i = 0) or ((AmmoTests[a].flags and amtest_NoTarget) = 0)) + then begin {$HINTS OFF} Score:= AmmoTests[a].proc(Me, Targets.ar[i].Point, BotLevel, ap); @@ -151,29 +153,45 @@ if (ap.Time <> 0) then AddAction(BestActions, aia_Timer, ap.Time div 1000, 400, 0, 0); + if (Ammoz[a].Ammo.Propz and ammoprop_NoCrosshair) = 0 then begin - ap.Angle:= LongInt(Me^.Angle) - Abs(ap.Angle); - if ap.Angle > 0 then + dAngle:= LongInt(Me^.Angle) - Abs(ap.Angle); + if dAngle > 0 then begin AddAction(BestActions, aia_Up, aim_push, 300 + random(250), 0, 0); - AddAction(BestActions, aia_Up, aim_release, ap.Angle, 0, 0) + AddAction(BestActions, aia_Up, aim_release, dAngle, 0, 0) end - else if ap.Angle < 0 then + else if dAngle < 0 then begin AddAction(BestActions, aia_Down, aim_push, 300 + random(250), 0, 0); - AddAction(BestActions, aia_Down, aim_release, -ap.Angle, 0, 0) + AddAction(BestActions, aia_Down, aim_release, -dAngle, 0, 0) end end; + if (Ammoz[a].Ammo.Propz and ammoprop_NeedTarget) <> 0 then begin AddAction(BestActions, aia_Put, 0, 1, ap.AttackPutX, ap.AttackPutY) end; - if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then + + if (Ammoz[a].Ammo.Propz and ammoprop_OscAim) <> 0 then begin - AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0); - AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); - end; + AddAction(BestActions, aia_attack, aim_push, 350 + random(200), 0, 0); + AddAction(BestActions, aia_attack, aim_release, 1, 0, 0); + + AddAction(BestActions, aia_Down, aim_push, 100 + random(150), 0, 0); + AddAction(BestActions, aia_Down, aim_release, 32, 0, 0); + + AddAction(BestActions, aia_waitAngle, ap.Angle, 250, 0, 0); + AddAction(BestActions, aia_attack, aim_push, 1, 0, 0); + AddAction(BestActions, aia_attack, aim_release, 1, 0, 0); + end else + if (Ammoz[a].Ammo.Propz and ammoprop_AttackingPut) = 0 then + begin + AddAction(BestActions, aia_attack, aim_push, 650 + random(300), 0, 0); + AddAction(BestActions, aia_attack, aim_release, ap.Power, 0, 0); + end; + if ap.ExplR > 0 then AddAction(BestActions, aia_AwareExpl, ap.ExplR, 10, ap.ExplX, ap.ExplY); end @@ -181,8 +199,8 @@ if a = High(TAmmoType) then a:= Low(TAmmoType) else inc(a) - until (a = aa) or (CurrentHedgehog^.MultiShootAttacks > 0) or // shooting same weapon - StopThinking + until (a = aa) or (CurrentHedgehog^.MultiShootAttacks > 0) {shooting same weapon} + or StopThinking end end; @@ -216,81 +234,86 @@ BestRate:= RatePlace(Me); BaseRate:= Max(BestRate, 0); +// switch to 'skip' if we can't move because of mouse cursor being shown if (Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NeedTarget) <> 0 then AddAction(Actions, aia_Weapon, Longword(amSkip), 100 + random(200), 0, 0); - -tmp:= random(2) + 1; -Push(0, Actions, Me^, tmp); -Push(0, Actions, Me^, tmp xor 3); -while (Stack.Count > 0) and (not StopThinking) and (GameFlags and gfArtillery = 0) do +if ((CurrentHedgehog^.MultiShootAttacks = 0) or ((Ammoz[Me^.Hedgehog^.CurAmmoType].Ammo.Propz and ammoprop_NoMoveAfter) = 0)) + and (GameFlags and gfArtillery = 0) then begin - Pop(ticks, Actions, Me^); + tmp:= random(2) + 1; + Push(0, Actions, Me^, tmp); + Push(0, Actions, Me^, tmp xor 3); + + while (Stack.Count > 0) and (not StopThinking) do + begin + Pop(ticks, Actions, Me^); - AddAction(Actions, Me^.Message, aim_push, 250, 0, 0); - if (Me^.Message and gmLeft) <> 0 then - AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) - else - AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); - - steps:= 0; + AddAction(Actions, Me^.Message, aim_push, 250, 0, 0); + if (Me^.Message and gmLeft) <> 0 then + AddAction(Actions, aia_WaitXL, hwRound(Me^.X), 0, 0, 0) + else + AddAction(Actions, aia_WaitXR, hwRound(Me^.X), 0, 0, 0); + + steps:= 0; - while (not StopThinking) do - begin -{$HINTS OFF} - CanGo:= HHGo(Me, @AltMe, GoInfo); -{$HINTS ON} - inc(ticks, GoInfo.Ticks); - if ticks > maxticks then - break; + while (not StopThinking) do + begin + {$HINTS OFF} + CanGo:= HHGo(Me, @AltMe, GoInfo); + {$HINTS ON} + inc(ticks, GoInfo.Ticks); + if ticks > maxticks then + break; - if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support - if Push(ticks, Actions, AltMe, Me^.Message) then - with Stack.States[Pred(Stack.Count)] do - begin - if Me^.dX.isNegative then - AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0) - else - AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0); + if (BotLevel < 5) and (GoInfo.JumpType = jmpHJump) then // hjump support + if Push(ticks, Actions, AltMe, Me^.Message) then + with Stack.States[Pred(Stack.Count)] do + begin + if Me^.dX.isNegative then + AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0) + else + AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0); + + AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0); + AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); - AddAction(MadeActions, aia_HJump, 0, 305 + random(50), 0, 0); - AddAction(MadeActions, aia_HJump, 0, 350, 0, 0); - - if Me^.dX.isNegative then - AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0) - else - AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0); - end; - if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support - if Push(ticks, Actions, AltMe, Me^.Message) then - with Stack.States[Pred(Stack.Count)] do - AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0); + if Me^.dX.isNegative then + AddAction(MadeActions, aia_LookLeft, 0, 200, 0, 0) + else + AddAction(MadeActions, aia_LookRight, 0, 200, 0, 0); + end; + if (BotLevel < 3) and (GoInfo.JumpType = jmpLJump) then // ljump support + if Push(ticks, Actions, AltMe, Me^.Message) then + with Stack.States[Pred(Stack.Count)] do + AddAction(MadeActions, aia_LJump, 0, 305 + random(50), 0, 0); - // 'not CanGO' means we can't go straight, possible jumps are checked above - if not CanGo then - break; - - inc(steps); - Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); - Rate:= RatePlace(Me); - if Rate > BestRate then - begin - BestActions:= Actions; - BestActions.isWalkingToABetterPlace:= true; - BestRate:= Rate; - Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo - end - else if Rate < BestRate then - break; - if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then - TestAmmos(Actions, Me, true); - if GoInfo.FallPix >= FallPixForBranching then - Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right - end {while}; + // 'not CanGO' means we can't go straight, possible jumps are checked above + if not CanGo then + break; + + inc(steps); + Actions.actions[Pred(Actions.Count)].Param:= hwRound(Me^.X); + Rate:= RatePlace(Me); + if Rate > BestRate then + begin + BestActions:= Actions; + BestActions.isWalkingToABetterPlace:= true; + BestRate:= Rate; + Me^.State:= Me^.State or gstAttacked // we have better place, go there and do not use ammo + end + else if Rate < BestRate then + break; + if ((Me^.State and gstAttacked) = 0) and ((steps mod 4) = 0) then + TestAmmos(Actions, Me, true); + if GoInfo.FallPix >= FallPixForBranching then + Push(ticks, Actions, Me^, Me^.Message xor 3); // aia_Left xor 3 = aia_Right + end {while}; - if BestRate > BaseRate then - exit + if BestRate > BaseRate then + exit end {while} + end {if} end; function Think(Me: Pointer): ptrint; @@ -412,6 +435,8 @@ AddFileLog('Thread started'); end; +//var scoreShown: boolean = false; + procedure ProcessBot; const cStopThinkTime = 40; begin @@ -428,16 +453,27 @@ StopMessages(Gear^.Message); TryDo((Gear^.Message and gmAllStoppable) = 0, 'Engine bug: AI may break demos playing', true); end; + if Gear^.Message <> 0 then exit; + + //scoreShown:= false; StartThink(Gear); StartTicks:= GameTicks - end else - ProcessAction(BestActions, Gear) + end else + begin + (* + if not scoreShown then + begin + if BestActions.Score > 0 then ParseCommand('/say Expected score = ' + inttostr(BestActions.Score div 1024), true); + scoreShown:= true + end;*) + ProcessAction(BestActions, Gear) + end else if ((GameTicks - StartTicks) > cMaxAIThinkTime) - or (TurnTimeLeft <= cStopThinkTime) then - StopThinking:= true + or (TurnTimeLeft <= cStopThinkTime) then + StopThinking:= true end; procedure initModule; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uAIActions.pas --- a/hedgewars/uAIActions.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uAIActions.pas Mon Jun 11 00:06:22 2012 +0200 @@ -43,6 +43,7 @@ aia_Skip = $8008; aia_Wait = $8009; aia_Put = $800A; + aia_waitAngle = $800B; aim_push = $8000; aim_release = $8001; @@ -70,7 +71,7 @@ var PrevX: LongInt = 0; timedelta: Longword = 0; -const ActionIdToStr: array[0..7] of string[16] = ( +const ActionIdToStr: array[0..8] of string[16] = ( {aia_none} '', {aia_Left} 'left', {aia_Right} 'right', @@ -78,7 +79,8 @@ {aia_attack} 'attack', {aia_Up} 'up', {aia_Down} 'down', -{aia_Switch} 'switch' +{aia_Switch} 'switch', +{aia_waitAngle} 'waitAngle' ); {$IFDEF TRACEAIACTIONS} @@ -150,6 +152,7 @@ begin repeat if Actions.Pos >= Actions.Count then exit; + with Actions.actions[Actions.Pos] do begin if Time > GameTicks then @@ -160,74 +163,77 @@ if (Action and ai_specmask) <> 0 then case Action of aia_Weapon: - SetWeapon(TAmmoType(Param)); + SetWeapon(TAmmoType(Param)); aia_WaitXL: - if hwRound(Me^.X) = Param then - begin - Action:= aia_LookLeft; - Time:= GameTicks; - exit - end - else if hwRound(Me^.X) < Param then + if hwRound(Me^.X) = Param then begin - //OutError('AI: WaitXL assert (' + IntToStr(hwRound(Me^.X)) + ' < ' + IntToStr(Param) + ')', false); - FreeActionsList; + Action:= aia_LookLeft; + Time:= GameTicks; + exit + end + else if hwRound(Me^.X) < Param then + begin + //OutError('AI: WaitXL assert (' + IntToStr(hwRound(Me^.X)) + ' < ' + IntToStr(Param) + ')', false); + FreeActionsList; + exit + end + else + begin + CheckHang(Me); + exit + end; + + aia_WaitXR: + if hwRound(Me^.X) = Param then + begin + Action:= aia_LookRight; + Time:= GameTicks; + exit + end + else if hwRound(Me^.X) > Param then + begin + //OutError('AI: WaitXR assert (' + IntToStr(hwRound(Me^.X)) + ' > ' + IntToStr(Param) + ')', false); + FreeActionsList; + exit + end + else + begin + CheckHang(Me); + exit + end; + aia_LookLeft: + if not Me^.dX.isNegative then + begin + ParseCommand('+left', true); exit end else - begin - CheckHang(Me); - exit - end; - - aia_WaitXR: - if hwRound(Me^.X) = Param then - begin - Action:= aia_LookRight; - Time:= GameTicks; - exit - end - else if hwRound(Me^.X) > Param then + ParseCommand('-left', true); + aia_LookRight: + if Me^.dX.isNegative then begin - //OutError('AI: WaitXR assert (' + IntToStr(hwRound(Me^.X)) + ' > ' + IntToStr(Param) + ')', false); - FreeActionsList; + ParseCommand('+right', true); exit end - else - begin - CheckHang(Me); - exit - end; - aia_LookLeft: - if not Me^.dX.isNegative then - begin - ParseCommand('+left', true); - exit - end - else - ParseCommand('-left', true); - aia_LookRight: - if Me^.dX.isNegative then - begin - ParseCommand('+right', true); - exit - end - else ParseCommand('-right', true); + else ParseCommand('-right', true); aia_AwareExpl: - AwareOfExplosion(X, Y, Param); + AwareOfExplosion(X, Y, Param); aia_HJump: - ParseCommand('hjump', true); + ParseCommand('hjump', true); aia_LJump: - ParseCommand('ljump', true); + ParseCommand('ljump', true); aia_Skip: - ParseCommand('skip', true); + ParseCommand('skip', true); aia_Put: - doPut(X, Y, true); + doPut(X, Y, true); + + aia_waitAngle: + if Me^.Angle <> Abs(Param) then exit; end else begin diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uAIAmmoTests.pas --- a/hedgewars/uAIAmmoTests.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uAIAmmoTests.pas Mon Jun 11 00:06:22 2012 +0200 @@ -21,7 +21,9 @@ unit uAIAmmoTests; interface uses SDLh, uConsts, uFloat, uTypes; -const amtest_OnTurn = $00000001; +const + amtest_OnTurn = $00000001; // from one position + amtest_NoTarget = $00000002; // each pos, but no targetting var windSpeed: real; @@ -41,6 +43,7 @@ function TestMortar(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestShotgun(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestDesertEagle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -68,9 +71,9 @@ (proc: nil; flags: 0), // amMine (proc: @TestDesertEagle; flags: 0), // amDEagle (proc: nil; flags: 0), // amDynamite - (proc: @TestFirePunch; flags: 0), // amFirePunch - (proc: @TestWhip; flags: 0), // amWhip - (proc: @TestBaseballBat; flags: 0), // amBaseballBat + (proc: @TestFirePunch; flags: amtest_NoTarget), // amFirePunch + (proc: @TestWhip; flags: amtest_NoTarget), // amWhip + (proc: @TestBaseballBat; flags: amtest_NoTarget), // amBaseballBat (proc: nil; flags: 0), // amParachute (proc: @TestAirAttack; flags: amtest_OnTurn), // amAirAttack (proc: nil; flags: 0), // amMineStrike @@ -95,7 +98,7 @@ (proc: nil; flags: 0), // amExtraTime (proc: nil; flags: 0), // amLaserSight (proc: nil; flags: 0), // amVampiric - (proc: nil; flags: 0), // amSniperRifle + (proc: @TestSniperRifle; flags: 0), // amSniperRifle (proc: nil; flags: 0), // amJetpack (proc: @TestMolotov; flags: 0), // amMolotov (proc: nil; flags: 0), // amBirdy @@ -105,7 +108,7 @@ (proc: @TestShotgun; flags: 0), // amSineGun (proc: nil; flags: 0), // amFlamethrower (proc: @TestGrenade; flags: 0), // amSMine - (proc: @TestHammer; flags: 0), // amHammer + (proc: @TestHammer; flags: amtest_NoTarget), // amHammer (proc: nil; flags: 0), // amResurrector (proc: nil; flags: 0), // amDrillStrike (proc: nil; flags: 0), // amSnowball @@ -600,7 +603,56 @@ TestDesertEagle:= BadTurn; exit(BadTurn); end; -t:= 0.5 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y)); +t:= 2 / sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y)); +Vx:= (Targ.X - x) * t; +Vy:= (Targ.Y - y) * t; +ap.Angle:= DxDy2AttackAnglef(Vx, -Vy); +d:= 0; + +repeat + x:= x + vX; + y:= y + vY; + if ((trunc(x) and LAND_WIDTH_MASK) = 0)and((trunc(y) and LAND_HEIGHT_MASK) = 0) + and (Land[trunc(y), trunc(x)] <> 0) then + inc(d); +until (Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5) + or (x < 0) + or (y < 0) + or (trunc(x) > LAND_WIDTH) + or (trunc(y) > LAND_HEIGHT) + or (d > 50); + +if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 5 then + begin + fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00125 * 20, vY * 0.00125 * 20); + if fallDmg < 0 then + valueResult:= 204800 + else valueResult:= Max(0, (4 - d div 50) * trunc((7+fallDmg)*dmgMod) * 1024) + end +else + valueResult:= BadTurn; +TestDesertEagle:= valueResult +end; + + +function TestSniperRifle(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; +var Vx, Vy, x, y, t, dmg, dmgMod: real; + d: Longword; + fallDmg, valueResult: LongInt; +begin +dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; +Level:= Level; // avoid compiler hint +ap.ExplR:= 0; +ap.Time:= 0; +ap.Power:= 1; +x:= hwFloat2Float(Me^.X); +y:= hwFloat2Float(Me^.Y); +if Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) < 40 then + exit(BadTurn); + +dmg:= sqrt(sqr(Targ.X - x)+sqr(Targ.Y-y)); +t:= 1.5 / dmg; +dmg:= dmg * 0.025; // div 40 Vx:= (Targ.X - x) * t; Vy:= (Targ.Y - y) * t; ap.Angle:= DxDy2AttackAnglef(Vx, -Vy); @@ -617,153 +669,172 @@ or (y < 0) or (trunc(x) > LAND_WIDTH) or (trunc(y) > LAND_HEIGHT) - or (d > 200); + or (d > 23); -if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 3 then +if Abs(Targ.X - trunc(x)) + Abs(Targ.Y - trunc(y)) < 4 then begin - fallDmg:= TraceShoveFall(Me, Targ.X, Targ.Y, vX * 0.005 * 20, vY * 0.005 * 20); + fallDmg:= TraceShoveFall(Targ.X, Targ.Y, vX * 0.00166 * dmg, vY * 0.00166 * dmg); if fallDmg < 0 then - valueResult:= 204800 - else valueResult:= Max(0, (4 - d div 50) * trunc((7+fallDmg)*dmgMod) * 1024) + TestSniperRifle:= BadTurn + else + TestSniperRifle:= Max(0, trunc((dmg + fallDmg) * dmgMod) * 1024) end else - valueResult:= BadTurn; -TestDesertEagle:= valueResult + TestSniperRifle:= BadTurn end; + function TestBaseballBat(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; -var valueResult: LongInt; - x, y: real; +var valueResult, a, v1, v2: LongInt; + x, y: LongInt; + dx, dy: real; begin -Level:= Level; // avoid compiler hint -TestBaseballBat:= BadTurn; -ap.ExplR:= 0; -x:= hwFloat2Float(Me^.X); -y:= hwFloat2Float(Me^.Y); -if (Level > 2) or (Abs(trunc(x) - Targ.X) + Abs(trunc(y) - Targ.Y) > 25) then - exit(BadTurn); + Level:= Level; // avoid compiler hint + ap.ExplR:= 0; + ap.Time:= 0; + ap.Power:= 1; + x:= hwRound(Me^.X); + y:= hwRound(Me^.Y); + + a:= 0; + valueResult:= 0; + + while a <= cMaxAngle div 2 do + begin + dx:= sin(a / cMaxAngle * pi) * 0.5; + dy:= cos(a / cMaxAngle * pi) * 0.5; -ap.Time:= 0; -ap.Power:= 1; -if (Targ.X) - trunc(x) >= 0 then - ap.Angle:= cMaxAngle div 4 -else - ap.Angle:= - cMaxAngle div 4; + v1:= RateShove(Me, x - 10, y + , 33, 30, 115 + , -dx, -dy, afTrackFall); + v2:= RateShove(Me, x + 10, y + , 33, 30, 115 + , dx, -dy, afTrackFall); + if (v1 > valueResult) or (v2 > valueResult) then + if (v2 > v1) + or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then + begin + ap.Angle:= a; + valueResult:= v2 + end + else + begin + ap.Angle:= -a; + valueResult:= v1 + end; -valueResult:= RateShove(Me, trunc(x) + LongWord(10*hwSignf(Targ.X - x)), trunc(y), 15, 30, 115, hwSign(Me^.dX)*0.353, -0.353, afTrackFall); -if valueResult <= 0 then - valueResult:= BadTurn -else - inc(valueResult); -TestBaseballBat:= valueResult; + a:= a + 15 + random(cMaxAngle div 16) + end; + + if valueResult <= 0 then + valueResult:= BadTurn; + + TestBaseballBat:= valueResult; end; function TestFirePunch(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; -var val1, val2, i, t: LongInt; - x, y: real; +var valueResult, v1, v2, i: LongInt; + x, y: LongInt; begin -Level:= Level; // avoid compiler hint -TestFirePunch:= BadTurn; -ap.ExplR:= 0; -ap.Time:= 0; -ap.Power:= 1; -ap.Angle:= hwSign(Me^.dX); -x:= hwFloat2Float(Me^.X); -y:= hwFloat2Float(Me^.Y); -{ -// this block is for digging with firepunch when blocked close to walls (notice TestColl check) -if (Abs(trunc(x) - Targ.X) > 25) - or (Abs(trunc(y) + 50 - Targ.Y) > 50) then - begin - if TestColl(trunc(x), trunc(y) - 16, 6) and - (RateShove(Me, trunc(x) + LongWord(10 * hwSign(Me^.dX)), - trunc(y) - 40, 30, 30, 40, hwSign(Me^.dX)*0.45, -0.9, 1) >= 0) then - val1:= Succ(BadTurn) - else - val1:= BadTurn; - exit(val1); - end; - } -// and this is actual try to attack -val1:= 0; -for i:= 0 to 4 do - begin - t:= RateShove(Me, trunc(x) + 10 * hwSignf(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, hwSign(Me^.dX)*0.45, -0.9, afTrackFall); - if (val1 < 0) or (t < 0) then val1:= BadTurn - else if t > 0 then val1:= t; - end; + Level:= Level; // avoid compiler hint + ap.ExplR:= 0; + ap.Time:= 0; + ap.Power:= 1; + x:= hwRound(Me^.X); + y:= hwRound(Me^.Y); + + v1:= 0; + for i:= 0 to 8 do + begin + v1:= v1 + RateShove(Me, x - 10, y - 10 * i + , 18, 30, 40 + , -0.45, -0.9, afTrackFall or afSetSkip); + end; + v1:= v1 + RateShove(Me, x - 10, y - 90 + , 18, 30, 40 + , -0.45, -0.9, afTrackFall); + -val2:= 0; -for i:= 0 to 4 do - begin - t:= RateShove(Me, trunc(x) + 10 * hwSignf(Targ.X - x), trunc(y) - 20 * i - 5, 10, 30, 40, -hwSign(Me^.dX)*0.45, -0.9, afTrackFall); - if (val2 < 0) or (t < 0) then val2:= BadTurn - else if t > 0 then val2:= t; - end; -if (val1 > val2) and (val1 > 0) then - TestFirePunch:= val1 -else if (val2 > val1) and (val2 > 0) then - begin - ap.Angle:= -hwSign(Me^.dX); - TestFirePunch:= val2 - end -else TestFirePunch:= BadTurn; + // now try opposite direction + v2:= 0; + for i:= 0 to 8 do + begin + v2:= v2 + RateShove(Me, x + 10, y - 10 * i + , 18, 30, 40 + , 0.45, -0.9, afTrackFall or afSetSkip); + end; + v2:= v2 + RateShove(Me, x + 10, y - 90 + , 18, 30, 40 + , 0.45, -0.9, afTrackFall); + + if (v2 > v1) + or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then + begin + ap.Angle:= 1; + valueResult:= v2 + end + else + begin + ap.Angle:= -1; + valueResult:= v1 + end; + + if valueResult <= 0 then + valueResult:= BadTurn; + + TestFirePunch:= valueResult; end; -// TODO: TestWhip, TestFirepunch and TestBaseballBat could be called only once at each position -// (now they're called for each possible target in each position) + function TestWhip(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; var valueResult, v1, v2: LongInt; - x, y: real; + x, y: LongInt; begin -Level:= Level; // avoid compiler hint -ap.ExplR:= 0; -ap.Time:= 0; -ap.Power:= 1; -x:= hwFloat2Float(Me^.X); -y:= hwFloat2Float(Me^.Y); + Level:= Level; // avoid compiler hint + ap.ExplR:= 0; + ap.Time:= 0; + ap.Power:= 1; + x:= hwRound(Me^.X); + y:= hwRound(Me^.Y); -if(abs(Targ.X - x) > 50) or (abs(Targ.Y - y) > 30) then // we're way too far from our target - exit(BadTurn); + // check left direction + {first RateShove checks farthermost of two whip's AmmoShove attacks + to encourage distant attacks (damaged hog is excluded from view of second + RateShove call)} + v1:= RateShove(Me, x - 15, y + , 30, 30, 25 + , -1, -0.8, afTrackFall or afSetSkip); + v1:= v1 + + RateShove(Me, x, y + , 30, 30, 25 + , -1, -0.8, afTrackFall); + // now try opposite direction + v2:= RateShove(Me, x + 15, y + , 30, 30, 25 + , 1, -0.8, afTrackFall or afSetSkip); + v2:= v2 + + RateShove(Me, x, y + , 30, 30, 25 + , 1, -0.8, afTrackFall); + + if (v2 > v1) + or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then + begin + ap.Angle:= 1; + valueResult:= v2 + end + else + begin + ap.Angle:= -1; + valueResult:= v1 + end; -// check left direction -{first RateShove checks fartherest of two whip's AmmoShove attacks -to encourage distant attacks (damaged hog is excluded from view of second -RateShove call)} -v1:= RateShove(Me, trunc(x) - 15, trunc(y) - , 30, 30, 40 - , -1, -0.8, afTrackFall or afSetSkip); -v1:= v1 + - RateShove(Me, trunc(x), trunc(y) - , 30, 30, 40 - , -1, -0.8, afTrackFall); -// now try opposite direction -v2:= RateShove(Me, trunc(x) + 15, trunc(y) - , 30, 30, 40 - , 1, -0.8, afTrackFall or afSetSkip); -v2:= v2 + - RateShove(Me, trunc(x), trunc(y) - , 30, 30, 40 - , 1, -0.8, afTrackFall); + if valueResult <= 0 then + valueResult:= BadTurn + else + inc(valueResult); -if (v2 > v1) - or {don't encourage turning for no gain}((v2 = v1) and (not Me^.dX.isNegative)) then - begin - ap.Angle:= 1; - valueResult:= v2 - end -else - begin - ap.Angle:= -1; - valueResult:= v1 - end; - -if valueResult <= 0 then - valueResult:= BadTurn -else - inc(valueResult); - -TestWhip:= valueResult; + TestWhip:= valueResult; end; function TestHammer(Me: PGear; Targ: TPoint; Level: LongInt; var ap: TAttackParams): LongInt; @@ -775,10 +846,7 @@ ap.Power:= 1; ap.Angle:= 0; -if (Abs(hwRound(Me^.X) + hwSign(Me^.dX) * 10 - Targ.X) + Abs(hwRound(Me^.Y) - Targ.Y) > 20) then - rate:= 0 -else - rate:= RateHammer(Me); +rate:= RateHammer(Me); if rate = 0 then rate:= BadTurn; TestHammer:= rate; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uAIMisc.pas --- a/hedgewars/uAIMisc.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uAIMisc.pas Mon Jun 11 00:06:22 2012 +0200 @@ -59,8 +59,9 @@ function RatePlace(Gear: PGear): LongInt; function TestColl(x, y, r: LongInt): boolean; inline; +function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; function TestCollExcludingMe(Me: PGear; x, y, r: LongInt): boolean; inline; -function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt; +function TraceShoveFall(x, y, dX, dY: Real): LongInt; function RateExplosion(Me: PGear; x, y, r: LongInt): LongInt; inline; function RateExplosion(Me: PGear; x, y, r: LongInt; Flags: LongWord): LongInt; @@ -80,7 +81,7 @@ end; implementation -uses uCollisions, uVariables, uUtils, uDebug; +uses uCollisions, uVariables, uUtils, uDebug, uLandTexture; const KillScore = 200; @@ -236,6 +237,28 @@ TestCollExcludingMe:= TestColl(x, y, r) end; +function TestCollExcludingObjects(x, y, r: LongInt): boolean; inline; +var b: boolean; +begin + b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x-r] and $FF00 <> 0); + if b then + exit(true); + + b:= (((x-r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x-r] and $FF00 <> 0); + if b then + exit(true); + + b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y-r) and LAND_HEIGHT_MASK) = 0) and (Land[y-r, x+r] and $FF00 <> 0); + if b then + exit(true); + + b:= (((x+r) and LAND_WIDTH_MASK) = 0) and (((y+r) and LAND_HEIGHT_MASK) = 0) and (Land[y+r, x+r] and $FF00 <> 0); + if b then + exit(true); + + TestCollExcludingObjects:= false; +end; + function TestColl(x, y, r: LongInt): boolean; inline; var b: boolean; begin @@ -311,16 +334,25 @@ end; end; -function TraceShoveFall(Me: PGear; x, y, dX, dY: Real): LongInt; -var dmg: LongInt; +function TraceShoveFall(x, y, dX, dY: Real): LongInt; +var dmg, v: LongInt; begin +v:= random($FFFFFFFF); while true do begin x:= x + dX; y:= y + dY; dY:= dY + cGravityf; +(* + if ((trunc(y) and LAND_HEIGHT_MASK) = 0) and ((trunc(x) and LAND_WIDTH_MASK) = 0) then + begin + LandPixels[trunc(y), trunc(x)]:= v; + UpdateLandTexture(trunc(X), 1, trunc(Y), 1, true); + end; +*) + // consider adding dX/dY calc here for fall damage - if TestCollExcludingMe(Me, trunc(x), trunc(y), cHHRadius) then + if TestCollExcludingObjects(trunc(x), trunc(y), cHHRadius) then begin if 0.4 < dY then begin @@ -398,8 +430,8 @@ dX, dY, dmgMod: real; begin fallDmg:= 0; -dX:= gdX * 0.005 * kick; -dY:= gdY * 0.005 * kick; +dX:= gdX * 0.01 * kick; +dY:= gdY * 0.01 * kick; dmgMod:= 0.01 * hwFloat2Float(cDamageModifier) * cDamagePercent; rate:= 0; for i:= 0 to Pred(Targets.Count) do @@ -410,15 +442,13 @@ begin dmg:= 0; if abs(Point.x - x) + abs(Point.y - y) < r then - begin dmg:= r - trunc(sqrt(sqr(Point.x - x)+sqr(Point.y - y))); - dmg:= trunc(dmg * dmgMod); - end; + if dmg > 0 then begin if (Flags and afSetSkip <> 0) then skip:= true; - if (Flags and afTrackFall <> 0) then - fallDmg:= trunc(TraceShoveFall(Me, Point.x, Point.y - 2, dX, dY) * dmgMod); + if (Flags and afTrackFall <> 0) and (Score > 0) then + fallDmg:= trunc(TraceShoveFall(Point.x, Point.y - 2, dX, dY) * dmgMod); if fallDmg < 0 then // drowning. score healthier hogs higher, since their death is more likely to benefit the AI if Score > 0 then inc(rate, KillScore + Score div 10) // Add a bit of a bonus for bigger hog drownings diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uCommandHandlers.pas Mon Jun 11 00:06:22 2012 +0200 @@ -436,7 +436,7 @@ end else TryDo(checksum = lastTurnChecksum, 'Desync detected', true); - AddFileLog('Doing SwitchHedgehog: time '+inttostr(GameTicks)); + AddFileLog('Next turn: time '+inttostr(GameTicks)); end; procedure chTimer(var s: shortstring); @@ -763,7 +763,8 @@ procedure chGameFlags(var s: shortstring); begin -GameFlags:= StrToInt(s) +GameFlags:= StrToInt(s); +if GameFlags and gfSharedAmmo <> 0 then GameFlags:= GameFlags and not gfPerHogAmmo end; procedure chHedgehogTurnTime(var s: shortstring); diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uConsts.pas --- a/hedgewars/uConsts.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uConsts.pas Mon Jun 11 00:06:22 2012 +0200 @@ -147,6 +147,7 @@ cBlowTorchC = 6; cKeyMaxIndex = 1023; + cKbdMaxIndex = 65536;//need more room for the modifier keys cHHFileName = 'Hedgehog'; cCHFileName = 'Crosshair'; @@ -259,6 +260,8 @@ ammoprop_Effect = $00002000; ammoprop_SetBounce = $00004000; ammoprop_NeedUpDown = $00008000;//Used by TouchInterface to show or hide up/down widgets + ammoprop_OscAim = $00010000; + ammoprop_NoMoveAfter = $00020000; ammoprop_NoRoundEnd = $10000000; AMMO_INFINITE = 100; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uGears.pas Mon Jun 11 00:06:22 2012 +0200 @@ -363,11 +363,11 @@ FreeActionsList; // could send -left, -right and similar commands, so should be called before /nextturn + ParseCommand('/nextturn', true); SwitchHedgehog; AfterSwitchHedgehog; - bBetweenTurns:= false; - ParseCommand('/nextturn', true) + bBetweenTurns:= false end; step:= Low(step) end; @@ -826,7 +826,7 @@ if PlacingHogs then Unplaced:= true else - FindPlace(Gear, false, t, t + LAND_WIDTH div 2);// could make Gear == nil; + FindPlace(Gear, false, t, t + LAND_WIDTH div 2, true);// could make Gear == nil; if Gear <> nil then begin Gear^.Pos:= GetRandom(49); @@ -859,7 +859,7 @@ if PlacingHogs then ar[i]^.Unplaced:= true else - FindPlace(ar[i]^.Gear, false, 0, LAND_WIDTH); + FindPlace(ar[i]^.Gear, false, 0, LAND_WIDTH, true); if ar[i]^.Gear <> nil then begin ar[i]^.Gear^.dX.isNegative:= hwRound(ar[i]^.Gear^.X) > LAND_WIDTH div 2; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uGearsHedgehog.pas Mon Jun 11 00:06:22 2012 +0200 @@ -707,12 +707,10 @@ if (Gear^.Message and gmLeft )<>0 then Gear^.dX:= -cLittle else if (Gear^.Message and gmRight )<>0 then - Gear^.dX:= cLittle else exit; + Gear^.dX:= cLittle + else exit; - if (Gear^.Message and (gmLeft or gmRight)) <> 0 then - begin - StepSoundTimer:= cHHStepTicks; - end; + StepSoundTimer:= cHHStepTicks; GHStepTicks:= cHHStepTicks; if PrevdX <> hwSign(Gear^.dX) then @@ -837,6 +835,7 @@ if (CurrentHedgehog^.Gear = Gear) and (hwSqr(Gear^.dX) + hwSqr(Gear^.dY) > _0_003) then begin + // TODO: why so aggressive at setting FollowGear when falling? FollowGear:= Gear; end; if isUnderwater then diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uGearsList.pas --- a/hedgewars/uGearsList.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uGearsList.pas Mon Jun 11 00:06:22 2012 +0200 @@ -246,7 +246,8 @@ gear^.ImpactSound:= sndGraveImpact; gear^.nImpactSounds:= 1; gear^.Radius:= 16; - gear^.Elasticity:= _0_3 + gear^.Elasticity:= _0_3; + gear^.Timer:= 0 end; gtExplosives: begin gear^.ImpactSound:= sndGrenadeImpact; @@ -545,7 +546,8 @@ inc(KilledHHs); RecountTeamHealth(team); if (CurrentHedgehog <> nil) and (CurrentHedgehog^.Effects[heResurrectable] <> 0) and - (Gear^.Hedgehog^.Effects[heResurrectable] = 0) then + //(Gear^.Hedgehog^.Effects[heResurrectable] = 0) then + (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan) then with CurrentHedgehog^ do begin inc(Team^.stats.AIKills); diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uGearsRender.pas Mon Jun 11 00:06:22 2012 +0200 @@ -989,7 +989,9 @@ DrawSpriteRotated(sprSMineOn, x, y, 0, Gear^.DirAngle) else DrawSpriteRotated(sprMineDead, x, y, 0, Gear^.DirAngle); - gtCase: if ((Gear^.Pos and posCaseAmmo) <> 0) then + gtCase: begin + if Gear^.Timer < 255 then Tint($FF, $FF, $FF, Gear^.Timer); + if ((Gear^.Pos and posCaseAmmo) <> 0) then begin i:= (GameTicks shr 6) mod 64; if i > 18 then @@ -1011,6 +1013,8 @@ i:= i mod 12; DrawSprite(sprUtility, x - 24, y - 24, i); end; + if Gear^.Timer < 255 then Tint($FF, $FF, $FF, $FF); + end; gtExplosives: begin if ((Gear^.State and gstDrowning) <> 0) then DrawSprite(sprExplosivesRoll, x - 24, y - 24, 0) diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uGearsUtils.pas Mon Jun 11 00:06:22 2012 +0200 @@ -452,7 +452,8 @@ gear^.Damage := 0; gear^.Health := gear^.Hedgehog^.InitialHealth; gear^.Hedgehog^.Effects[hePoisoned] := 0; - if CurrentHedgehog^.Effects[heResurrectable] = 0 then + if (CurrentHedgehog^.Effects[heResurrectable] = 0) or ((CurrentHedgehog^.Effects[heResurrectable] <> 0) + and (Gear^.Hedgehog^.Team^.Clan <> CurrentHedgehog^.Team^.Clan)) then with CurrentHedgehog^ do begin inc(Team^.stats.AIKills); @@ -474,6 +475,7 @@ if gear <> nil then begin AddVisualGear(hwRound(gear^.X), hwRound(gear^.Y), vgtExplosion); + PlaySound(sndWarp); RenderHealth(gear^.Hedgehog^); ScriptCall('onGearResurrect', gear^.uid); gear^.State := gstWait; @@ -481,13 +483,13 @@ RecountTeamHealth(tempTeam); end; -function CountNonZeroz(x, y, r, c: LongInt): LongInt; +function CountNonZeroz(x, y, r, c: LongInt; mask: LongWord): LongInt; var i: LongInt; count: LongInt = 0; begin if (y and LAND_HEIGHT_MASK) = 0 then for i:= max(x - r, 0) to min(x + r, LAND_WIDTH - 4) do - if Land[y, i] <> 0 then + if Land[y, i] and mask <> 0 then begin inc(count); if count = c then @@ -529,9 +531,10 @@ ar2: array[0..1023] of TPoint; cnt, cnt2: Longword; delta: LongInt; - reallySkip, tryAgain: boolean; + ignoreNearObjects, ignoreOverlap, tryAgain: boolean; begin -reallySkip:= false; // try not skipping proximity at first +ignoreNearObjects:= false; // try not skipping proximity at first +ignoreOverlap:= false; // this not only skips proximity, but allows overlapping objects (barrels, mines, hogs, crates). Saving it for a 3rd pass. With this active, winning AI Survival goes back to virtual impossibility tryAgain:= true; while tryAgain do begin @@ -547,23 +550,27 @@ begin repeat inc(y, 2); - until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) = 0); + until (y >= cWaterLine) or + (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) = 0)) or + (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FF00) = 0)); sy:= y; repeat inc(y); - until (y >= cWaterLine) or (CountNonZeroz(x, y, Gear^.Radius - 1, 1) <> 0); + until (y >= cWaterLine) or + (not ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FFFF) <> 0)) or + (ignoreOverlap and (CountNonZeroz(x, y, Gear^.Radius - 1, 1, $FF00) <> 0)); if (y - sy > Gear^.Radius * 2) and (((Gear^.Kind = gtExplosives) and (y < cWaterLine) - and (reallySkip or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60)) - and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1) > Gear^.Radius)) + and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 60, 60)) + and (CountNonZeroz(x, y+1, Gear^.Radius - 1, Gear^.Radius+1, $FFFF) > Gear^.Radius)) or ((Gear^.Kind <> gtExplosives) and (y < cWaterLine) - and (reallySkip or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110)) + and (ignoreNearObjects or NoGearsToAvoid(x, y - Gear^.Radius, 110, 110)) )) then begin ar[cnt].X:= x; @@ -588,10 +595,12 @@ dec(Delta, 60) until (cnt2 > 0) or (Delta < 70); - if (cnt2 = 0) and skipProximity and (not reallySkip) then + // if either of these has not been tried, do another pass + if (cnt2 = 0) and skipProximity and (not ignoreOverlap) then tryAgain:= true else tryAgain:= false; - reallySkip:= true; + if ignoreNearObjects then ignoreOverlap:= true; + ignoreNearObjects:= true; end; if cnt2 > 0 then diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uInputHandler.pas --- a/hedgewars/uInputHandler.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uInputHandler.pas Mon Jun 11 00:06:22 2012 +0200 @@ -25,7 +25,9 @@ procedure initModule; procedure freeModule; -function KeyNameToCode(name: shortstring): word; +function KeyNameToCode(name: shortstring; Modifier: shortstring = ''): LongInt; +procedure MaskModifier(var code: LongInt; modifier: LongWord); +procedure MaskModifier(Modifier: shortstring; var code: LongInt); procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean); procedure ProcessKey(event: TSDL_KeyboardEvent); inline; procedure ProcessKey(code: LongInt; KeyDown: boolean); @@ -45,37 +47,79 @@ implementation uses uConsole, uCommands, uMisc, uVariables, uConsts, uUtils, uDebug; -var tkbd: array[0..cKeyMaxIndex] of boolean; +const + LSHIFT = $0200; + RSHIFT = $0400; + LALT = $0800; + RALT = $1000; + LCTRL = $2000; + RCTRL = $4000; + +var tkbd: array[0..cKbdMaxIndex] of boolean; quitKeyCode: Byte; KeyNames: array [0..cKeyMaxIndex] of string[15]; CurrentBinds: TBinds; -function KeyNameToCode(name: shortstring): word; -var code: Word; +function KeyNameToCode(name: shortstring; Modifier: shortstring): LongInt; +var code: LongInt; begin name:= LowerCase(name); code:= cKeyMaxIndex; while (code > 0) and (KeyNames[code] <> name) do dec(code); + + MaskModifier(Modifier, code); KeyNameToCode:= code; end; +procedure MaskModifier(var code: LongInt; Modifier: LongWord); +begin + if(Modifier and KMOD_LSHIFT) <> 0 then code:= code or LSHIFT; + if(Modifier and KMOD_RSHIFT) <> 0 then code:= code or LSHIFT; + if(Modifier and KMOD_LALT) <> 0 then code:= code or LALT; + if(Modifier and KMOD_RALT) <> 0 then code:= code or LALT; + if(Modifier and KMOD_LCTRL) <> 0 then code:= code or LCTRL; + if(Modifier and KMOD_RCTRL) <> 0 then code:= code or LCTRL; +end; + +procedure MaskModifier(Modifier: shortstring; var code: LongInt); +var mod_ : shortstring; + ModifierCount, i: LongInt; +begin +if Modifier = '' then exit; +ModifierCount:= 0; + +for i:= 1 to Length(Modifier) do + if(Modifier[i] = ':') then inc(ModifierCount); + +SplitByChar(Modifier, mod_, ':');//remove the first mod: part +Modifier:= mod_; +for i:= 0 to ModifierCount do + begin + mod_:= ''; + SplitByChar(Modifier, mod_, ':'); + if (Modifier = 'lshift') then code:= code or LSHIFT; + if (Modifier = 'rshift') then code:= code or RSHIFT; + if (Modifier = 'lalt') then code:= code or LALT; + if (Modifier = 'ralt') then code:= code or RALT; + if (Modifier = 'lctrl') or (mod_ = 'lmeta') then code:= code or LCTRL; + if (Modifier = 'rctrl') or (mod_ = 'rmeta') then code:= code or RCTRL; + Modifier:= mod_; + end; +end; + procedure ProcessKey(code: LongInt; KeyDown: boolean); var Trusted: boolean; s : string; begin - if not(tkbd[code] xor KeyDown) then exit; tkbd[code]:= KeyDown; - hideAmmoMenu:= false; Trusted:= (CurrentTeam <> nil) and (not CurrentTeam^.ExtDriven) and (CurrentHedgehog^.BotLevel = 0); - - // ctrl/cmd + q to close engine and frontend if(KeyDown and (code = quitKeyCode)) then begin @@ -109,8 +153,11 @@ end; procedure ProcessKey(event: TSDL_KeyboardEvent); inline; +var code: LongInt; begin - ProcessKey(event.keysym.sym, event.type_ = SDL_KEYDOWN); + code:= event.keysym.sym; + //MaskModifier(code, event.keysym.modifier); + ProcessKey(code, event.type_ = SDL_KEYDOWN); end; procedure ProcessMouse(event: TSDL_MouseButtonEvent; ButtonDown: boolean); @@ -132,7 +179,7 @@ procedure ResetKbd; var t: LongInt; begin -for t:= 0 to cKeyMaxIndex do +for t:= 0 to cKbdMaxIndex do if tkbd[t] then ProcessKey(t, False); end; @@ -239,11 +286,19 @@ end; procedure SetBinds(var binds: TBinds); +{$IFNDEF MOBILE} +var + t: LongInt; +{$ENDIF} begin {$IFDEF MOBILE} binds:= binds; // avoid hint CurrentBinds:= DefaultBinds; {$ELSE} +for t:= 0 to cKbdMaxIndex do + if (CurrentBinds[t] <> binds[t]) and tkbd[t] then + ProcessKey(t, False); + CurrentBinds:= binds; {$ENDIF} end; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uLand.pas --- a/hedgewars/uLand.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uLand.pas Mon Jun 11 00:06:22 2012 +0200 @@ -674,7 +674,7 @@ end end; -UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT); +UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); end; procedure GenPreview(out Preview: TPreview); diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uLandGraphics.pas Mon Jun 11 00:06:22 2012 +0200 @@ -463,7 +463,7 @@ dx:= Min(X + Radius + 1, LAND_WIDTH) - tx; ty:= Max(Y - Radius - 1, 0); dy:= Min(Y + Radius + 1, LAND_HEIGHT) - ty; -UpdateLandTexture(tx, dx, ty, dy); +UpdateLandTexture(tx, dx, ty, dy, false); DrawExplosion:= cnt end; @@ -515,7 +515,7 @@ end; -UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT) +UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false) end; // @@ -665,7 +665,7 @@ ddx:= Min(stX + HalfWidth * 2 + 4 + abs(hwRound(dX * ticks)), LAND_WIDTH) - tx; ddy:= Min(stY + HalfWidth * 2 + 4 + abs(hwRound(dY * ticks)), LAND_HEIGHT) - ty; -UpdateLandTexture(tx, ddx, ty, ddy) +UpdateLandTexture(tx, ddx, ty, ddy, false) end; function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean; indestructible: boolean): boolean; @@ -753,7 +753,7 @@ w:= Min(cpX + Image^.w, LAND_WIDTH) - x; y:= Max(cpY, topY); h:= Min(cpY + Image^.h, LAND_HEIGHT) - y; -UpdateLandTexture(x, w, y, h) +UpdateLandTexture(x, w, y, h, true) end; function Despeckle(X, Y: LongInt): boolean; @@ -955,7 +955,7 @@ end; end; if updateBlock then - UpdateLandTexture(tx, 32, ty, 32); + UpdateLandTexture(tx, 32, ty, 32, false); LandDirty[y, x]:= 2; end; end; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uLandTexture.pas --- a/hedgewars/uLandTexture.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uLandTexture.pas Mon Jun 11 00:06:22 2012 +0200 @@ -24,17 +24,17 @@ procedure initModule; procedure freeModule; -procedure UpdateLandTexture(X, Width, Y, Height: LongInt); +procedure UpdateLandTexture(X, Width, Y, Height: LongInt; landAdded: boolean); procedure DrawLand(dX, dY: LongInt); procedure ResetLand; implementation uses uConsts, GLunit, uTypes, uVariables, uTextures, uDebug, uRender; -const TEXSIZE = 512; +const TEXSIZE = 128; type TLandRecord = record - shouldUpdate: boolean; + shouldUpdate, landAdded: boolean; tex: PTexture; end; @@ -62,7 +62,7 @@ Pixels2:= @tmpPixels end; -procedure UpdateLandTexture(X, Width, Y, Height: LongInt); +procedure UpdateLandTexture(X, Width, Y, Height: LongInt; landAdded: boolean); var tx, ty: Longword; begin if (Width <= 0) or (Height <= 0) then @@ -75,16 +75,24 @@ if (cReducedQuality and rqBlurryLand) = 0 then for ty:= Y div TEXSIZE to (Y + Height - 1) div TEXSIZE do for tx:= X div TEXSIZE to (X + Width - 1) div TEXSIZE do - LandTextures[tx, ty].shouldUpdate:= true + begin + LandTextures[tx, ty].shouldUpdate:= true; + LandTextures[tx, ty].landAdded:= landAdded + end else for ty:= (Y div TEXSIZE) div 2 to ((Y + Height - 1) div TEXSIZE) div 2 do for tx:= (X div TEXSIZE) div 2 to ((X + Width - 1) div TEXSIZE) div 2 do + begin LandTextures[tx, ty].shouldUpdate:= true; + LandTextures[tx, ty].landAdded:= landAdded + end end; procedure RealLandTexUpdate; -var x, y: LongWord; +var x, y, ty, tx, lx, ly : LongWord; + isEmpty: boolean; begin +(* if LandTextures[0, 0].tex = nil then for x:= 0 to LANDTEXARW -1 do for y:= 0 to LANDTEXARH - 1 do @@ -95,14 +103,67 @@ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, tpHigh); end else +*) for x:= 0 to LANDTEXARW -1 do for y:= 0 to LANDTEXARH - 1 do with LandTextures[x, y] do if shouldUpdate then begin shouldUpdate:= false; - glBindTexture(GL_TEXTURE_2D, tex^.id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y)); + isEmpty:= not landAdded; + landAdded:= false; + ty:= 0; + tx:= 1; + ly:= y * TEXSIZE; + lx:= x * TEXSIZE; + // first check edges + while isEmpty and (ty < TEXSIZE) do + begin + isEmpty:= LandPixels[ly + ty, lx] and AMask = 0; + if isEmpty then isEmpty:= LandPixels[ly + ty, lx + TEXSIZE-1] and AMask = 0; + inc(ty) + end; + while isEmpty and (tx < TEXSIZE-1) do + begin + isEmpty:= LandPixels[ly, lx + tx] and AMask = 0; + if isEmpty then isEmpty:= LandPixels[ly + TEXSIZE-1, lx + tx] and AMask = 0; + inc(tx) + end; + // then search every other remaining. does this sort of stuff defeat compiler opts? + ty:= 2; + while isEmpty and (ty < TEXSIZE-1) do + begin + tx:= 2; + while isEmpty and (tx < TEXSIZE-1) do + begin + isEmpty:= LandPixels[ly + ty, lx + tx] and AMask = 0; + inc(tx,2) + end; + inc(ty,2); + end; + // and repeat + ty:= 1; + while isEmpty and (ty < TEXSIZE-1) do + begin + tx:= 1; + while isEmpty and (tx < TEXSIZE-1) do + begin + isEmpty:= LandPixels[ly + ty, lx + tx] and AMask = 0; + inc(tx,2) + end; + inc(ty,2); + end; + if not isEmpty then + begin + if tex = nil then tex:= NewTexture(TEXSIZE, TEXSIZE, Pixels(x, y)); + glBindTexture(GL_TEXTURE_2D, tex^.id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y)); + end + else if tex <> nil then + begin + FreeTexture(tex); + tex:= nil + end; end end; @@ -114,10 +175,11 @@ for x:= 0 to LANDTEXARW -1 do for y:= 0 to LANDTEXARH - 1 do with LandTextures[x, y] do - if (cReducedQuality and rqBlurryLand) = 0 then - DrawTexture(dX + x * TEXSIZE, dY + y * TEXSIZE, tex) - else - DrawTexture(dX + x * TEXSIZE * 2, dY + y * TEXSIZE * 2, tex, 2.0) + if tex <> nil then + if (cReducedQuality and rqBlurryLand) = 0 then + DrawTexture(dX + x * TEXSIZE, dY + y * TEXSIZE, tex) + else + DrawTexture(dX + x * TEXSIZE * 2, dY + y * TEXSIZE * 2, tex, 2.0) end; @@ -144,8 +206,11 @@ for y:= 0 to LANDTEXARH - 1 do with LandTextures[x, y] do begin - FreeTexture(tex); - tex:= nil; + if tex <> nil then + begin + FreeTexture(tex); + tex:= nil + end end; end; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uStore.pas --- a/hedgewars/uStore.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uStore.pas Mon Jun 11 00:06:22 2012 +0200 @@ -1118,7 +1118,7 @@ ReloadLines; StoreLoad(true); // redraw all land - UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT); + UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false); end; end; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uTeams.pas --- a/hedgewars/uTeams.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uTeams.pas Mon Jun 11 00:06:22 2012 +0200 @@ -248,8 +248,6 @@ FollowGear:= Gear end; -ResetKbd; - if (GameFlags and gfDisableWind) = 0 then begin cWindSpeed:= rndSign(GetRandomf * 2 * cMaxWindSpeed); @@ -554,22 +552,33 @@ end; procedure chBind(var id: shortstring); -var s: shortstring; +var KeyName, Modifier, tmp: shortstring; b: LongInt; begin -s:= ''; +KeyName:= ''; +Modifier:= ''; + if CurrentTeam = nil then exit; -SplitBySpace(id, s); -if s[1]='"' then - Delete(s, 1, 1); -if s[byte(s[0])]='"' then - Delete(s, byte(s[0]), 1); -b:= KeyNameToCode(id); + +if(Pos('mod:', id) <> 0)then + begin + tmp:= ''; + SplitBySpace(id, tmp); + Modifier:= id; + id:= tmp; + end; + +SplitBySpace(id, KeyName); +if KeyName[1]='"' then + Delete(KeyName, 1, 1); +if KeyName[byte(KeyName[0])]='"' then + Delete(KeyName, byte(KeyName[0]), 1); +b:= KeyNameToCode(id, Modifier); if b = 0 then OutError(errmsgUnknownVariable + ' "' + id + '"', false) else - CurrentTeam^.Binds[b]:= s + CurrentTeam^.Binds[b]:= KeyName; end; procedure chTeamGone(var s:shortstring); diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uTouch.pas --- a/hedgewars/uTouch.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uTouch.pas Mon Jun 11 00:06:22 2012 +0200 @@ -62,8 +62,11 @@ const clickTime = 200; nilFingerId = High(TSDL_FingerId); + baseRectSize = 96; var + rectSize, halfRectSize: LongInt; + pointerCount : Longword; fingers: array of TTouch_Data; moveCursor : boolean; @@ -551,8 +554,10 @@ x := 0;//avoid compiler hint y := 0; convertToFingerCoord(x, y, CrosshairX, CrosshairY); - isOnCrosshair:= sqrt(sqr(finger.x-x) + sqr(finger.y-y)) < 50; -// isOnCrosshair:= isOnRect(x-24, y-24, 48, 48, finger); + isOnCrosshair:= isOnRect((x-HalfRectSize), (y-HalfRectSize), RectSize, RectSize, finger); + printFinger(finger); + WriteLnToConsole(inttostr(finger.x) + ' ' + inttostr(x)); + WriteLnToConsole(inttostr(x) + ' ' + inttostr(y) + ' ' + inttostr(round(Android_JNI_getDensity() * 10))); end; function isOnCurrentHog(finger: TTouch_Data): boolean; @@ -562,7 +567,7 @@ x := 0; y := 0; convertToFingerCoord(x,y, hwRound(CurrentHedgehog^.Gear^.X), hwRound(CurrentHedgehog^.Gear^.Y)); - isOnCurrentHog := sqrt(sqr(finger.X-x) + sqr(finger.Y-y)) < 50; + isOnCurrentHog:= isOnRect((x-HalfRectSize), (y-HalfRectSize), RectSize, RectSize, finger); end; procedure convertToFingerCoord(var x,y : LongInt; oldX, oldY: LongInt); @@ -627,12 +632,22 @@ var index: Longword; //uRenderCoordScaleX, uRenderCoordScaleY: Longword; + density: Single; begin buttonsDown:= 0; setLength(fingers, 4); for index := 0 to High(fingers) do fingers[index].id := nilFingerId; + +{$IFDEF ANDROID} + density:= Android_JNI_getDensity(); +{$ELSE} + density:= 1.0; +{$ENDIF} + + rectSize:= round(baseRectSize * density); + halfRectSize:= rectSize shl 1; end; begin diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uTypes.pas Mon Jun 11 00:06:22 2012 +0200 @@ -308,7 +308,7 @@ TeamDamage : Longword; end; - TBinds = array[0..cKeyMaxIndex] of shortstring; + TBinds = array[0..cKbdMaxIndex] of shortstring; TKeyboardState = array[0..cKeyMaxIndex] of Byte; PVoicepack = ^TVoicepack; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uUtils.pas --- a/hedgewars/uUtils.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uUtils.pas Mon Jun 11 00:06:22 2012 +0200 @@ -24,6 +24,7 @@ uses uTypes, uFloat, GLunit; procedure SplitBySpace(var a, b: shortstring); +procedure SplitByChar(var a, b: shortstring; c: char); procedure SplitByChar(var a, b: ansistring; c: char); {$IFNDEF PAS2C} @@ -83,11 +84,16 @@ {$ENDIF} var CharArray: array[byte] of Char; +procedure SplitBySpace(var a,b: shortstring); +begin +SplitByChar(a,b,' '); +end; + // should this include "strtolower()" for the split string? -procedure SplitBySpace(var a, b: shortstring); +procedure SplitByChar(var a, b: shortstring; c : char); var i, t: LongInt; begin -i:= Pos(' ', a); +i:= Pos(c, a); if i > 0 then begin for t:= 1 to Pred(i) do diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uVariables.pas Mon Jun 11 00:06:22 2012 +0200 @@ -1828,7 +1828,9 @@ NameTex: nil; Probability: 20; NumberInCase: 2; - Ammo: (Propz: ammoprop_NeedUpDown; + Ammo: (Propz: ammoprop_NeedUpDown or + ammoprop_OscAim or + ammoprop_NoMoveAfter; Count: 2; NumPerTurn: 1; Timer: 0; diff -r 076aba32abd3 -r 8d04e85ca204 hedgewars/uWorld.pas --- a/hedgewars/uWorld.pas Mon Jun 11 00:02:17 2012 +0200 +++ b/hedgewars/uWorld.pas Mon Jun 11 00:06:22 2012 +0200 @@ -1512,9 +1512,6 @@ DrawTexture((cScreenWidth shr 1) - 60 - offsetY, offsetX, fpsTexture); end; - if CountTicks >= 1000 then - CountTicks:= 0; - // lag warning (?) inc(SoundTimerTicks, Lag); end; @@ -1606,7 +1603,10 @@ {$ENDIF} z:= round(200/zoom); if not PlacingHogs and (FollowGear <> nil) and (not isCursorVisible) and (not bShowAmmoMenu) and (not fastUntilLag) then - if (not autoCameraOn) or ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then + if (not autoCameraOn) then + FollowGear:= nil + else + if ((abs(CursorPoint.X - prevPoint.X) + abs(CursorPoint.Y - prevpoint.Y)) > 4) then begin FollowGear:= nil; prevPoint:= CursorPoint; @@ -1656,7 +1656,7 @@ EdgesDist:= cGearScrEdgesDist; // this generates the border around the screen that moves the camera when cursor is near it -if isCursorVisible or (FollowGear <> nil) then +if isCursorVisible or ((FollowGear <> nil) and autoCameraOn) then begin if CursorPoint.X < - cScreenWidth div 2 + EdgesDist then begin diff -r 076aba32abd3 -r 8d04e85ca204 project_files/Android-build/SDL-android-project/jni/SDL/src/core/android/SDL_android.cpp --- a/project_files/Android-build/SDL-android-project/jni/SDL/src/core/android/SDL_android.cpp Mon Jun 11 00:02:17 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/jni/SDL/src/core/android/SDL_android.cpp Mon Jun 11 00:06:22 2012 +0200 @@ -638,16 +638,12 @@ return Android_JNI_FileClose(ctx, true); } -/******************************************************************************* - Functions called by the hwengine into Java -*******************************************************************************/ - -extern "C" float Android_JNI_getDensity(){ +extern "C" int Android_JNI_getDensity(){ jmethodID mid; - jfloat density; + jint density; //SDLActivity.getDensity() - mid = mEnv->GetStaticMethodID(mActivityClass, "getDensity", "()F"); - if(!mid) return 1.5f; + mid = mEnv->GetStaticMethodID(mActivityClass, "getDensity", "()I"); + if(!mid) return 160; density = mEnv->CallStaticFloatMethod(mActivityClass, mid); return density; diff -r 076aba32abd3 -r 8d04e85ca204 project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java --- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Mon Jun 11 00:02:17 2012 +0200 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Mon Jun 11 00:06:22 2012 +0200 @@ -403,9 +403,9 @@ } } - public static float getDensity(){ + public static int getDensity(){ DisplayMetrics dm = SDLActivity.getContext().getResources().getDisplayMetrics(); - return dm.density; + return dm.densityDpi; } } diff -r 076aba32abd3 -r 8d04e85ca204 share/hedgewars/Data/Scripts/Multiplayer/WxW.lua --- a/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua Mon Jun 11 00:02:17 2012 +0200 +++ b/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua Mon Jun 11 00:06:22 2012 +0200 @@ -598,7 +598,7 @@ roundN = roundN + 1 if roundN < 2 then TurnTimeLeft = -1 - SetInputMask(band(0xFFFFFFFF, bnot(gmAnimate+gmAttack+gmDown+gmHJump+gmLeft+gmLJump+gmPrecise+gmRight+gmSlot+gmSwitch+gmTimer+gmUp+gmWeapon))) + SetInputMask(0) allowCrate = false HandleStartingStage() -- new end @@ -670,7 +670,7 @@ then SetInputMask(0xFFFFFFFF) elseif ropeG == nil then - SetInputMask(band(0xFFFFFFFF, bnot(gmAttack))) + SetInputMask(bnot(gmAttack)) end end