--- a/.hgtags Mon Nov 02 06:23:46 2015 +0100
+++ b/.hgtags Mon Nov 02 06:58:08 2015 +0100
@@ -64,3 +64,6 @@
7e55468ffe384a3065524c483eb5e3cdb1658fd5 0.9.21-release
7e55468ffe384a3065524c483eb5e3cdb1658fd5 fab746a3597e
0f5961910e2712582b162abd08ae3eed330cc978 Nice one
+d9622394ec9c2974a84b9b4d9e6c0ac26c4060ff 0.9.22-RC
+0f5961910e2712582b162abd08ae3eed330cc978 Nice one
+0000000000000000000000000000000000000000 Nice one
--- a/CMakeLists.txt Mon Nov 02 06:23:46 2015 +0100
+++ b/CMakeLists.txt Mon Nov 02 06:58:08 2015 +0100
@@ -55,7 +55,7 @@
set(CPACK_PACKAGE_VERSION_MAJOR 0)
set(CPACK_PACKAGE_VERSION_MINOR 9)
set(CPACK_PACKAGE_VERSION_PATCH 22)
-set(HEDGEWARS_PROTO_VER 50)
+set(HEDGEWARS_PROTO_VER 51)
set(HEDGEWARS_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
include(${CMAKE_MODULE_PATH}/revinfo.cmake)
--- a/ChangeLog.txt Mon Nov 02 06:23:46 2015 +0100
+++ b/ChangeLog.txt Mon Nov 02 06:58:08 2015 +0100
@@ -2,10 +2,11 @@
* bugfixes
0.9.21 -> 0.9.22
+ + New Weapon / Map object: AirMine (floating mine that will follow nearby hedgehogs)
+ Extensive changes to TechRacer: Variable terrain types, enhanced parameters, hwmap interpreter, fuel limiter, etc.
+ Map previews can now take script parameters into account and preview waypoints in TechRacer
+ Added a couple new flags
- + Small improvements to the interface and in-game chat
+ + Various tweaks to the interface and in-game chat
+ Divided teams options will now just be ignored when more/less than 2 teams, instead of displaying a fatal error
+ Added 6 TechRacer maps to TechMaps
+ Added 3 SpeedShoppa Challenges: Shoppa Love, Ropes and Crates, The Customer is King
@@ -13,10 +14,20 @@
+ Improved "Art" theme.
* Generated bridges/girders are now connected better to the land mass
* Fixed rubberband sprite
+ * Fixed Wind-Indicator being wrong in certain situations
+ * Melon Bomb Pieces now bounce on Rubberband
+ * Reduced menu music volume
* The game will now fallback to default voicepack if a team's voicepack is not locally installed. (Instead of rendering team voiceless)
* Hammer now does more damage when the Extra-Damage utility is used
* Many other bug fixes
+Lua-API:
+ + New map parameter: MapFeatureSize -- numeric representation of detail slider below map preview; use within onGameInit()/onPreviewInit()
+ + New function: SetMaxBuildDistance([ distInPx ]) -- specify how many pixels away a hedgehog can still place girders/etc. set to 0 for no limit; call with no param to reset to default
+ + New hook: onSuddenDeath() -- called by engine when sudden death begins
+ * Previously missing gear states are now available (gstSubmersible, gstFrozen and gstNoGravity)
+ * Fixed OnHogAttack giving the incorrect AmmoType (amNothing) under certain conditions
+
0.9.20 -> 0.9.21:
+ New type of randomly generated maps: Perlin Maps.
+ Old Random generated maps are more diverse now.
--- a/gameServer/Actions.hs Mon Nov 02 06:23:46 2015 +0100
+++ b/gameServer/Actions.hs Mon Nov 02 06:58:08 2015 +0100
@@ -757,15 +757,15 @@
processAction (CheckFailed msg) = do
- Just (CheckInfo fileName _) <- client's checkInfo
+ Just (CheckInfo fileName _ _) <- client's checkInfo
io $ moveFailedRecord fileName
processAction (CheckSuccess info) = do
- Just (CheckInfo fileName teams) <- client's checkInfo
+ Just (CheckInfo fileName teams script) <- client's checkInfo
p <- client's clientProto
si <- gets serverInfo
- io $ writeChan (dbQueries si) $ StoreAchievements p (B.pack fileName) (map toPair teams) info
+ io $ writeChan (dbQueries si) $ StoreAchievements p (B.pack fileName) (map toPair teams) script info
io $ moveCheckedRecord fileName
where
toPair t = (teamname t, teamowner t)
--- a/gameServer/CoreTypes.hs Mon Nov 02 06:23:46 2015 +0100
+++ b/gameServer/CoreTypes.hs Mon Nov 02 06:58:08 2015 +0100
@@ -119,7 +119,8 @@
CheckInfo
{
recordFileName :: String,
- recordTeams :: [TeamInfo]
+ recordTeams :: [TeamInfo],
+ recordScript :: B.ByteString
}
data ClientInfo =
@@ -345,7 +346,7 @@
CheckAccount ClientIndex Int B.ByteString B.ByteString
| ClearCache
| SendStats Int Int
- | StoreAchievements Word16 B.ByteString [(B.ByteString, B.ByteString)] [B.ByteString]
+ | StoreAchievements Word16 B.ByteString [(B.ByteString, B.ByteString)] B.ByteString [B.ByteString]
| GetReplayName ClientIndex Int B.ByteString
deriving (Show, Read)
--- a/gameServer/EngineInteraction.hs Mon Nov 02 06:23:46 2015 +0100
+++ b/gameServer/EngineInteraction.hs Mon Nov 02 06:58:08 2015 +0100
@@ -100,8 +100,8 @@
-> Map.Map B.ByteString B.ByteString
-> Map.Map B.ByteString [B.ByteString]
-> [B.ByteString]
- -> [B.ByteString]
-replayToDemo ti mParams prms msgs = if not sane then [] else concat [
+ -> ([B.ByteString], [B.ByteString])
+replayToDemo ti mParams prms msgs = if not sane then ([], []) else ([scriptName], concat [
[em "TD"]
, maybeScript
, maybeMap
@@ -117,7 +117,7 @@
, concatMap teamSetup ti
, msgs
, [em "!"]
- ]
+ ])
where
keys1, keys2 :: Set.Set B.ByteString
keys1 = Set.fromList ["FEATURE_SIZE", "MAP", "MAPGEN", "MAZE_SIZE", "SEED", "TEMPLATE"]
@@ -127,7 +127,8 @@
&& (not . null . drop 41 $ scheme)
&& (not . null . tail $ prms Map.! "AMMO")
mapGenTypes = ["+rnd+", "+maze+", "+drawn+", "+perlin+"]
- maybeScript = let s = head . fromMaybe ["Normal"] $ Map.lookup "SCRIPT" prms in if s == "Normal" then [] else [eml ["escript Scripts/Multiplayer/", s, ".lua"]]
+ scriptName = head . fromMaybe ["Normal"] $ Map.lookup "SCRIPT" prms
+ maybeScript = let s = scriptName in if s == "Normal" then [] else [eml ["escript Scripts/Multiplayer/", s, ".lua"]]
maybeMap = let m = mParams Map.! "MAP" in if m `elem` mapGenTypes then [] else [eml ["emap ", m]]
scheme = tail $ prms Map.! "SCHEME"
mapgen = mParams Map.! "MAPGEN"
--- a/gameServer/OfficialServer/GameReplayStore.hs Mon Nov 02 06:23:46 2015 +0100
+++ b/gameServer/OfficialServer/GameReplayStore.hs Mon Nov 02 06:58:08 2015 +0100
@@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\-}
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}
module OfficialServer.GameReplayStore where
import Data.Time
@@ -70,11 +70,12 @@
where
loadFile :: String -> IO (Maybe CheckInfo, [B.ByteString])
loadFile fileName = E.handle (\(e :: SomeException) ->
- warningM "REPLAYS" ("Problems reading " ++ fileName ++ ": " ++ show e) >> return (Just $ CheckInfo fileName [], [])) $ do
+ warningM "REPLAYS" ("Problems reading " ++ fileName ++ ": " ++ show e) >> return (Just $ CheckInfo fileName [] "", [])) $ do
(teams, params1, params2, roundMsgs) <- liftM read $ readFile fileName
- return $ (
- Just (CheckInfo fileName teams)
- , let d = replayToDemo teams (Map.fromList params1) (Map.fromList params2) (reverse roundMsgs) in d `deepseq` d
+ let d = replayToDemo teams (Map.fromList params1) (Map.fromList params2) (reverse roundMsgs)
+ d `deepseq` return $ (
+ Just (CheckInfo fileName teams (head $ fst d))
+ , snd d
)
moveFailedRecord :: String -> IO ()
--- a/gameServer/OfficialServer/extdbinterface.hs Mon Nov 02 06:23:46 2015 +0100
+++ b/gameServer/OfficialServer/extdbinterface.hs Mon Nov 02 06:58:08 2015 +0100
@@ -50,6 +50,9 @@
\ VALUES (?, (SELECT id FROM achievement_types WHERE name = ?), (SELECT uid FROM users WHERE name = ?), \
\ ?, ?, ?, ?)"
+dbQueryGamesHistory =
+ "? ? ?"
+
dbQueryReplayFilename = "SELECT filename FROM achievements WHERE id = ?"
@@ -83,8 +86,8 @@
SendStats clients rooms ->
void $ execute dbConn dbQueryStats (clients, rooms)
- StoreAchievements p fileName teams info ->
- mapM_ (execute dbConn dbQueryAchievement) $ (parseStats p fileName teams) info
+ StoreAchievements p fileName teams script info ->
+ mapM_ (uncurry (execute dbConn)) $ parseStats p fileName teams script info
--readTime = read . B.unpack . B.take 19 . B.drop 8
@@ -94,15 +97,16 @@
Word16
-> B.ByteString
-> [(B.ByteString, B.ByteString)]
- -> [B.ByteString]
- -> [(B.ByteString, B.ByteString, B.ByteString, Int, B.ByteString, B.ByteString, Int)]
-parseStats p fileName teams = ps
+ -> B.ByteString
+ -> [B.ByteString]
+ -> [(Query, (B.ByteString, B.ByteString, B.ByteString, Int, B.ByteString, B.ByteString, Int))]
+parseStats p fileName teams script = ps
where
time = readTime fileName
ps [] = []
ps ("DRAW" : bs) = ps bs
ps ("WINNERS" : n : bs) = ps $ drop (readInt_ n) bs
- ps ("ACHIEVEMENT" : typ : teamname : location : value : bs) =
+ ps ("ACHIEVEMENT" : typ : teamname : location : value : bs) = (dbQueryAchievement,
( time
, typ
, fromMaybe "" (lookup teamname teams)
@@ -110,7 +114,7 @@
, fileName
, location
, fromIntegral p
- ) : ps bs
+ )) : ps bs
ps (b:bs) = ps bs
--- a/hedgewars/uGears.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGears.pas Mon Nov 02 06:58:08 2015 +0100
@@ -320,6 +320,7 @@
Ammoz[amTardis].Probability:= 0;
end;
AddCaption(trmsg[sidSuddenDeath], cWhiteColor, capgrpGameState);
+ ScriptCall('onSuddenDeath');
playSound(sndSuddenDeath);
StopMusic;
if SDMusicFN <> '' then PlayMusic
--- a/hedgewars/uGearsHandlersMess.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGearsHandlersMess.pas Mon Nov 02 06:58:08 2015 +0100
@@ -2675,7 +2675,7 @@
//4: FollowGear := AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtWaterMelon, 0, cBombsSpeed *
// Gear^.Tag, _0, 5000);
end;
- Gear^.dX := Gear^.dX + int2hwFloat(30 * Gear^.Tag);
+ Gear^.dX := Gear^.dX + int2hwFloat(Gear^.Damage * Gear^.Tag);
if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y)) then
FollowGear^.State:= FollowGear^.State or gstSubmersible;
StopSoundChan(Gear^.SoundChannel, 4000);
@@ -2708,7 +2708,7 @@
end;
Gear^.Y := int2hwFloat(topY-300);
- Gear^.dX := int2hwFloat(Gear^.Target.X - 5 * Gear^.Tag * 15);
+ Gear^.dX := int2hwFloat(Gear^.Target.X) - int2hwFloat(Gear^.Tag * Gear^.Health * Gear^.Damage) / 2;
// calcs for Napalm Strike, so that it will hit the target (without wind at least :P)
if (Gear^.State = 2) then
@@ -2718,7 +2718,6 @@
Gear^.dX := Gear^.dX - cBombsSpeed * hwSqrt((int2hwFloat(Gear^.Target.Y) - Gear^.Y) * 2 /
cGravity) * Gear^.Tag;
- Gear^.Health := 6;
Gear^.doStep := @doStepAirAttackWork;
Gear^.SoundChannel := LoopSound(sndPlane, 4000);
@@ -5198,7 +5197,9 @@
////////////////////////////////////////////////////////////////////////////////
procedure doStepPoisonCloud(Gear: PGear);
begin
- WorldWrap(Gear);
+ // don't bounce
+ if WorldEdge <> weBounce then
+ WorldWrap(Gear);
if Gear^.Timer = 0 then
begin
DeleteGear(Gear);
@@ -5430,7 +5431,7 @@
for i:= 0 to graves.size - 1 do
if graves.ar^[i]^.Health > 0 then
begin
- resgear := AddGear(hwRound(graves.ar^[i]^.X), hwRound(graves.ar^[i]^.Y), gtHedgehog, gstWait, _0, _0, 0);
+ resgear := AddGear(hwRound(graves.ar^[i]^.X), hwRound(graves.ar^[i]^.Y), gtHedgehog, gstWait, _0, _0, 0,graves.ar^[i]^.Pos);
resgear^.Hedgehog := graves.ar^[i]^.Hedgehog;
resgear^.Health := graves.ar^[i]^.Health;
PHedgehog(graves.ar^[i]^.Hedgehog)^.Gear := resgear;
@@ -5792,9 +5793,16 @@
All these effects assume the ray's angle is not changed and that the target type was unchanged over a number of ticks. This is a simplifying assumption for "gun was applying freezing effect to the same target".
* When fired at water a layer of ice textured land is added above the water.
* When fired at non-ice land (land and lfLandMask and not lfIce) the land is overlaid with a thin layer of ice textured land around that point (say, 1 or 2px into land, 1px above). For attractiveness, a slope would probably be needed.
- * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen. As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head. If the effect is interrupted before reaching the top, the freezing state is cleared.
-A frozen hog will animate differently. To be decided, but possibly in a similar fashion to a grave when it comes to explosions. The hog might (possibly) not be damaged by explosions. This might make freezing potentially useful for friendlies in a bad position. It might be better to allow damage though.
-A frozen hog stays frozen for a certain number of turns. Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again.
+ * When fired at a hog (land and $00FF <> 0), while the hog is targetted, the hog's state is set to frozen.
+ As long as the gun is on the hog, a frozen hog sprite creeps up from the feet to the head.
+ If the effect is interrupted before reaching the top, the freezing state is cleared.
+A frozen hog will animate differently.
+ To be decided, but possibly in a similar fashion to a grave when it comes to explosions.
+ The hog might (possibly) not be damaged by explosions.
+ This might make freezing potentially useful for friendlies in a bad position.
+ It might be better to allow damage though.
+A frozen hog stays frozen for a certain number of turns.
+ Each turn the frozen overlay becomes fainter, until it fades and the hog animates normally again.
*)
--- a/hedgewars/uGearsHandlersRope.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGearsHandlersRope.pas Mon Nov 02 06:58:08 2015 +0100
@@ -42,7 +42,8 @@
OutError('ERROR: doStepRopeAfterAttack called while HHGear = nil', IsNilHHFatal);
DeleteGear(Gear);
exit()
- end;
+ end
+ else if not CurrentTeam^.ExtDriven then FollowGear := HHGear;
tX:= HHGear^.X;
if WorldWrap(HHGear) and (WorldEdge = weWrap) and
@@ -137,7 +138,8 @@
OutError('ERROR: doStepRopeWork called while HHGear = nil', IsNilHHFatal);
DeleteGear(Gear);
exit()
- end;
+ end
+ else if not CurrentTeam^.ExtDriven then FollowGear := HHGear;
if ((HHGear^.State and gstHHDriven) = 0) or
(CheckGearDrowning(HHGear)) or (Gear^.PortalCounter <> 0) then
@@ -425,6 +427,7 @@
HHGear: PGear;
tx, ty, tt: hwFloat;
begin
+
Gear^.X := Gear^.X - Gear^.dX;
Gear^.Y := Gear^.Y - Gear^.dY;
Gear^.Elasticity := Gear^.Elasticity + _1;
@@ -435,7 +438,8 @@
OutError('ERROR: doStepRopeAttach called while HHGear = nil', IsNilHHFatal);
DeleteGear(Gear);
exit()
- end;
+ end
+ else if not CurrentTeam^.ExtDriven then FollowGear := HHGear;
DeleteCI(HHGear);
--- a/hedgewars/uGearsHedgehog.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGearsHedgehog.pas Mon Nov 02 06:58:08 2015 +0100
@@ -451,7 +451,7 @@
if CurAmmoType = amAirMine then newGear^.Hedgehog:= nil;
if ((CurAmmoType = amMine) or (CurAmmoType = amSMine) or (CurAmmoType = amAirMine)) and (GameFlags and gfInfAttack <> 0) then
- newGear^.FlightTime:= GameTicks + 1000
+ newGear^.FlightTime:= GameTicks + min(TurnTimeLeft,1000)
else if CurAmmoType = amDrill then
newGear^.FlightTime:= GameTicks + 250;
if Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NeedTarget <> 0 then
@@ -572,6 +572,7 @@
procedure doStepHedgehogDead(Gear: PGear);
const frametime = 200;
timertime = frametime * 6;
+var grave: PGear;
begin
if Gear^.Hedgehog^.Unplaced then
exit;
@@ -587,7 +588,10 @@
Gear^.Hedgehog^.Effects[heFrozen]:= 0;
Gear^.State:= Gear^.State or gstNoDamage;
doMakeExplosion(hwRound(Gear^.X), hwRound(Gear^.Y), 30, CurrentHedgehog, EXPLAutoSound);
- AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0)^.Hedgehog:= Gear^.Hedgehog;
+ grave:= AddGear(hwRound(Gear^.X), hwRound(Gear^.Y), gtGrave, 0, _0, _0, 0);
+ grave^.Hedgehog:= Gear^.Hedgehog;
+ grave^.Pos:= Gear^.uid;
+
DeleteGear(Gear);
SetAllToActive
end
--- a/hedgewars/uGearsList.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGearsList.pas Mon Nov 02 06:58:08 2015 +0100
@@ -23,6 +23,7 @@
uses uFloat, uTypes, SDLh;
function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
+function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer, newUid: LongWord): PGear;
procedure DeleteGear(Gear: PGear);
procedure InsertGearToList(Gear: PGear);
procedure RemoveGearFromList(Gear: PGear);
@@ -164,11 +165,16 @@
function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer: LongWord): PGear;
+begin
+AddGear:= AddGear(X, Y, Kind, State, dX, dY, Timer, 0);
+end;
+function AddGear(X, Y: LongInt; Kind: TGearType; State: Longword; dX, dY: hwFloat; Timer, newUid: LongWord): PGear;
var gear: PGear;
//c: byte;
cakeData: PCakeData;
begin
-inc(GCounter);
+if newUid = 0 then
+ inc(GCounter);
AddFileLog('AddGear: #' + inttostr(GCounter) + ' (' + inttostr(x) + ',' + inttostr(y) + '), d(' + floattostr(dX) + ',' + floattostr(dY) + ') type = ' + EnumToStr(Kind));
@@ -186,7 +192,9 @@
gear^.doStep:= doStepHandlers[Kind];
gear^.CollisionIndex:= -1;
gear^.Timer:= Timer;
-gear^.uid:= GCounter;
+if newUid = 0 then
+ gear^.uid:= GCounter
+else gear^.uid:= newUid;
gear^.SoundChannel:= -1;
gear^.ImpactSound:= sndNone;
gear^.Density:= _1;
@@ -466,6 +474,8 @@
gear^.Tag:= Y
end;
gtAirAttack: begin
+ gear^.Health:= 6;
+ gear^.Damage:= 30;
gear^.Z:= cHHZ+2;
gear^.Tint:= gear^.Hedgehog^.Team^.Clan^.Color shl 8 or $FF
end;
--- a/hedgewars/uGearsRender.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGearsRender.pas Mon Nov 02 06:58:08 2015 +0100
@@ -728,7 +728,7 @@
amHellishBomb: DrawSpriteRotated(sprHandHellish, hx, hy, sign, aangle);
amGasBomb: DrawSpriteRotated(sprHandCheese, hx, hy, sign, aangle);
amMine: DrawSpriteRotated(sprHandMine, hx, hy, sign, aangle);
- amAirMine: DrawSpriteRotated(sprHandMine, hx, hy, sign, aangle);
+ amAirMine: DrawSpriteRotated(sprHandAirMine, hx, hy, sign, aangle);
amSMine: DrawSpriteRotated(sprHandSMine, hx, hy, sign, aangle);
amKnife: DrawSpriteRotatedF(sprHandKnife, hx, hy, 0, sign, aangle);
amSeduction: begin
--- a/hedgewars/uGearsUtils.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uGearsUtils.pas Mon Nov 02 06:58:08 2015 +0100
@@ -829,7 +829,7 @@
procedure FindPlace(var Gear: PGear; withFall: boolean; Left, Right: LongInt; skipProximity: boolean);
var x: LongInt;
- y, sy: LongInt;
+ y, sy, dir: LongInt;
ar: array[0..1023] of TPoint;
ar2: array[0..2047] of TPoint;
temp: TPoint;
@@ -850,9 +850,10 @@
delta:= LAND_WIDTH div 16;
cnt2:= 0;
repeat
- x:= Left + max(LAND_WIDTH div 2048, LongInt(GetRandom(Delta)));
+ if GetRandom(2) = 0 then dir:= -1 else dir:= 1;
+ x:= max(LAND_WIDTH div 2048, LongInt(GetRandom(Delta)));
+ if dir = 1 then x:= Left + x else x:= Right - x;
repeat
- inc(x, Delta);
cnt:= 0;
y:= min(1024, topY) - Gear^.Radius shl 1;
while y < cWaterLine do
@@ -901,9 +902,10 @@
ar2[cnt2].x:= x;
ar2[cnt2].y:= y;
inc(cnt2)
- end
- end
- until (x + Delta > Right);
+ end;
+ end;
+ inc(x, Delta*dir)
+ until ((dir = 1) and (x > Right)) or ((dir = -1) and (x < Left));
dec(Delta, 60)
until (cnt2 > 0) or (Delta < 70);
--- a/hedgewars/uScript.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uScript.pas Mon Nov 02 06:58:08 2015 +0100
@@ -629,7 +629,9 @@
begin
gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
HealthCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
- lua_pushinteger(L, gear^.uid);
+ if gear <> nil then
+ lua_pushinteger(L, gear^.uid)
+ else lua_pushnil(L)
end
else
lua_pushnil(L);
@@ -643,7 +645,9 @@
begin
gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
AmmoCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
- lua_pushinteger(L, gear^.uid);
+ if gear <> nil then
+ lua_pushinteger(L, gear^.uid)
+ else lua_pushnil(L)
end
else
lua_pushnil(L);
@@ -657,7 +661,9 @@
begin
gear := SpawnFakeCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2),
UtilityCrate, lua_toboolean(L, 3), lua_toboolean(L, 4));
- lua_pushinteger(L, gear^.uid);
+ if gear <> nil then
+ lua_pushinteger(L, gear^.uid)
+ else lua_pushnil(L)
end
else
lua_pushnil(L);
@@ -676,9 +682,8 @@
health:= cHealthCaseAmount;
gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), HealthCrate, health, 0);
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
- else
- lua_pushnil(L);
+ lua_pushinteger(L, gear^.uid)
+ else lua_pushnil(L);
end
else
lua_pushnil(L);
@@ -695,9 +700,8 @@
gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), 0)
else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), AmmoCrate, lua_tointeger(L, 3), lua_tointeger(L, 4));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
- else
- lua_pushnil(L);
+ lua_pushinteger(L, gear^.uid)
+ else lua_pushnil(L);
end
else
lua_pushnil(L);
@@ -714,9 +718,8 @@
gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), 0)
else gear := SpawnCustomCrateAt(lua_tointeger(L, 1), lua_tointeger(L, 2), UtilityCrate, lua_tointeger(L, 3), lua_tointeger(L, 4));
if gear <> nil then
- lua_pushinteger(L, gear^.uid)
- else
- lua_pushnil(L);
+ lua_pushinteger(L, gear^.uid)
+ else lua_pushnil(L);
end
else
lua_pushnil(L);
@@ -918,29 +921,30 @@
lua_pushinteger(L, gear^.AdvBounce);
lua_pushinteger(L, Integer(gear^.ImpactSound));
lua_pushinteger(L, gear^.nImpactSounds);
- lua_pushinteger(L, gear^.Tint)
+ lua_pushinteger(L, gear^.Tint);
+ lua_pushinteger(L, gear^.Damage)
end
else
begin
lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
- lua_pushnil(L)
+ lua_pushnil(L); lua_pushnil(L)
end
end
else
begin
lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L); lua_pushnil(L);
- lua_pushnil(L)
+ lua_pushnil(L); lua_pushnil(L)
end;
- lc_getgearvalues:= 11
+ lc_getgearvalues:= 12
end;
function lc_setgearvalues(L : Plua_State) : LongInt; Cdecl;
var gear : PGear;
begin
-// Currently allows 1-12 params
-// if CheckLuaParamCount(L, 12, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint') then
+// Currently allows 1-13 params
+// if CheckLuaParamCount(L, 13, 'SetGearValues', 'gearUid, Angle, Power, WDTimer, Radius, Density, Karma, DirAngle, AdvBounce, ImpactSound, # ImpactSounds, Tint, Damage') then
// begin
gear:= GearByUID(lua_tointeger(L, 1));
if gear <> nil then
@@ -966,7 +970,9 @@
if not lua_isnoneornil(L, 11) then
gear^.nImpactSounds := lua_tointeger(L, 11);
if not lua_isnoneornil(L, 12) then
- gear^.Tint := lua_tointeger(L, 12)
+ gear^.Tint := lua_tointeger(L, 12);
+ if not lua_isnoneornil(L, 13) then
+ gear^.Damage := lua_tointeger(L, 13);
end;
// end
// else
@@ -2907,6 +2913,12 @@
procedure GetGlobals;
begin
+// TODO
+// Use setters instead, because globals should be read-only!
+// Otherwise globals might be changed by Lua, but then unexpectatly overwritten by engine when a ScriptCall is triggered by whatever Lua is doing!
+// Sure, one could work around that in engine (e.g. by setting writable globals in SetGlobals only when their engine-side value has actually changed since SetGlobals was called the last time...), but things just get messier and messier then.
+// It is inconsistent anyway to have some globals be read-only and others not with no indication whatsoever.
+// -- sheepluva
TurnTimeLeft:= ScriptGetInteger('TurnTimeLeft');
end;
--- a/hedgewars/uTeams.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uTeams.pas Mon Nov 02 06:58:08 2015 +0100
@@ -604,7 +604,6 @@
SplitBySpace(s, cs);
SplitBySpace(cs, ts);
Color:= StrToInt(cs);
- TryDo(Color <> 0, 'Error: black team color', true);
// color is always little endian so the mask must be constant also in big endian archs
Color:= Color or $FF000000;
--- a/hedgewars/uTypes.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uTypes.pas Mon Nov 02 06:58:08 2015 +0100
@@ -88,7 +88,7 @@
sprBulletHit, sprSnowball, sprHandSnowball, sprSnow,
sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis,
sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun,
- sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine
+ sprFrozenHog, sprAmRubber, sprBoing, sprCustom1, sprCustom2, sprAirMine, sprHandAirMine
);
// Gears that interact with other Gears and/or Land
--- a/hedgewars/uVariables.pas Mon Nov 02 06:23:46 2015 +0100
+++ b/hedgewars/uVariables.pas Mon Nov 02 06:58:08 2015 +0100
@@ -722,7 +722,9 @@
(FileName: 'custom2'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLow; getDimensions: true; getImageDimensions: true), // sprCustom2
(FileName: 'AirMine'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true)// sprAirMine
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true), // sprAirMine
+ (FileName: 'amAirMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true) // sprHandAirMine
);
const
Binary file share/hedgewars/Data/Graphics/Hedgehog/amAirMine.png has changed
--- a/share/hedgewars/Data/Locale/tips_en.xml Mon Nov 02 06:23:46 2015 +0100
+++ b/share/hedgewars/Data/Locale/tips_en.xml Mon Nov 02 06:58:08 2015 +0100
@@ -11,7 +11,7 @@
<tip>You're bored of default gameplay? Try one of the missions — they'll offer different gameplay depending on the one you picked.</tip>
<tip>By default the game will always record the last game played as a demo. Select “Local Game” and pick the “Demos” button on the lower right corner to play or manage them.</tip>
<tip>Hedgewars is free software (Open Source) we create in our spare time. If you’ve got problems, ask on our forums or visit our IRC room!</tip>
- <tip>Hedgewars is free software (Open Source) we create in our spare time. If you like it, help us with a small donation or contribute your own work!</tip>
+ <tip>Hedgewars is free software (Open Source) we create in our spare time. If you like it, feel free to help us with a small donation or contribute your own work!</tip>
<tip>Hedgewars is free software (Open Source) we create in our spare time. Share it with your family and friends as you like!</tip>
<tip>Hedgewars is free software (Open Source) we create in our spare time, just for fun! Meet the devs in <a href="irc://irc.freenode.net/hedgewars">#hedgewars</a>!</tip>
<tip>From time to time there will be official tournaments. Upcoming events will be announced at <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> some days in advance.</tip>
@@ -19,14 +19,13 @@
<tip>Hedgewars can be run on lots of different operating systems including Microsoft Windows, Mac OS X and GNU/Linux.</tip>
<tip>Always remember you’re able to set up your own games in local and network/online play. You’re not restricted to the “Simple Game” option.</tip>
<tip>Connect one or more gamepads before starting the game to be able to assign their controls to your teams.</tip>
- <tip>Create an account on <a href="http://www.hedgewars.org/">http://www.hedgewars.org/</a> to keep others from using your most favourite nickname while playing on the official server.</tip>
- <tip>While playing you should give yourself a short break at least once an hour.</tip>
+ <tip>Consider giving yourself a short break at least once an hour to guard against strain from playing.</tip>
<tip>If your graphics card isn’t able to provide hardware accelerated OpenGL, try to enable the low quality mode to improve performance.</tip>
<tip>If your graphics card isn’t able to provide hardware accelerated OpenGL, try to update the associated drivers.</tip>
<tip>We’re open to suggestions and constructive feedback. If you don’t like something or got a great idea, let us know!</tip>
- <tip>Especially while playing online be polite and always remember there might be some minors playing with or against you as well!</tip>
+ <tip>For your own benefit we'd like you to be polite and friendly while playing on our server. Also please keep in mind that some players are minors!</tip>
<tip>Special game modes such as “Vampirism” or “Karma” allow you to develop completely new tactics. Try them in a custom game!</tip>
- <tip>You should never install Hedgewars on computers you don’t own (school, university, work, etc.). Please ask the responsible person instead!</tip>
+ <tip>Please don't install Hedgewars on computers you don’t own (school, university, work, etc.) unless you got permission. We don't want you to get into any trouble.</tip>
<tip>Hedgewars can be perfect for short games during breaks. Just ensure you don’t add too many hedgehogs or use an huge map. Reducing time and health might help as well.</tip>
<tip>No hedgehogs were harmed in making this game.</tip>
<tip>There are three different jumps available. Tap [high jump] twice to do a very high/backwards jump.</tip>
--- a/share/hedgewars/Data/Maps/Basketball/map.lua Mon Nov 02 06:23:46 2015 +0100
+++ b/share/hedgewars/Data/Maps/Basketball/map.lua Mon Nov 02 06:58:08 2015 +0100
@@ -54,3 +54,7 @@
end
end
end
+
+function onNewTurn()
+ SetWeapon(amBaseballBat)
+end
--- a/share/hedgewars/Data/Maps/Knockball/map.lua Mon Nov 02 06:23:46 2015 +0100
+++ b/share/hedgewars/Data/Maps/Knockball/map.lua Mon Nov 02 06:58:08 2015 +0100
@@ -68,3 +68,7 @@
end
end
end
+
+function onNewTurn()
+ SetWeapon(amBaseballBat)
+end
--- a/share/hedgewars/Data/Maps/TrophyRace/map.lua Mon Nov 02 06:23:46 2015 +0100
+++ b/share/hedgewars/Data/Maps/TrophyRace/map.lua Mon Nov 02 06:58:08 2015 +0100
@@ -33,6 +33,7 @@
local worsthog = nil
local besthog = nil
+local besthogname = ''
-- best time
local besttime = maxtime + 1
@@ -78,7 +79,8 @@
SetHealth(CurrentHedgehog, 0)
SetEffect(CurrentHedgehog, heInvulnerable, 0)
x, y = GetGearPosition(CurrentHedgehog)
- AddGear(x, y, gtShell, 0, 0, 0, 0)
+ AddGear(x, y-2, gtGrenade, 0, 0, 0, 2)
+ SetGearVelocity(CurrentHedgehog, 0, 0)
worsttime = 99999
worsthog = nil
lasthog = nil
@@ -141,6 +143,7 @@
if ttime < besttime then
besttime = ttime
besthog = CurrentHedgehog
+ besthogname = GetHogName(besthog)
hscore = hscore .. loc("NEW fastest lap: ")
else
hscore = hscore .. loc("Fastest lap: ")
@@ -149,7 +152,7 @@
worsttime = ttime
worsthog = CurrentHedgehog
end
- hscore = hscore .. GetHogName(besthog) .. " - " .. (besttime / 1000) .. " s | |" .. loc("Best laps per team: ")
+ hscore = hscore .. besthogname .. " - " .. (besttime / 1000) .. " s | |" .. loc("Best laps per team: ")
if clan == ClansCount -1 then
-- Time for elimination - worst hog is out and the worst hog vars are reset.