# HG changeset patch # User koda # Date 1361977977 -3600 # Node ID 9d1d0fa8db02ec24ccc2769c8073a5765b9028dd # Parent 9afb44f030b6f359321cdfc24040523035b6fb39# Parent e96bf10216ef5b5aba7d8d8c956c1d74e01cc446 merge physfslayer in default diff -r e96bf10216ef -r 9d1d0fa8db02 .hgignore --- a/.hgignore Mon Feb 25 19:48:35 2013 +0100 +++ b/.hgignore Wed Feb 27 16:12:57 2013 +0100 @@ -59,4 +59,5 @@ glob:*.depends glob:tools/build_windows_koda.bat glob:share/hedgewars/Data/misc/hwengine.desktop - +glob:*.exe +glob:_CPack_Packages/ diff -r e96bf10216ef -r 9d1d0fa8db02 QTfrontend/hwform.cpp --- a/QTfrontend/hwform.cpp Mon Feb 25 19:48:35 2013 +0100 +++ b/QTfrontend/hwform.cpp Wed Feb 27 16:12:57 2013 +0100 @@ -350,6 +350,7 @@ } } + ui.Pages->setCurrentIndex(ID_PAGE_INFO); PagesStack.push(ID_PAGE_MAIN); ((AbstractPage*)ui.Pages->widget(ID_PAGE_MAIN))->triggerPageEnter(); GoBack(); @@ -1234,13 +1235,12 @@ hwnet, SLOT(askRoomsList())); // room status stuff -// not queued because creates new signal/slot connection connect(hwnet, SIGNAL(roomMaster(bool)), - this, SLOT(NetGameChangeStatus(bool))); + this, SLOT(NetGameChangeStatus(bool)), Qt::QueuedConnection); // net page stuff connect(hwnet, SIGNAL(roomNameUpdated(const QString &)), - ui.pageNetGame, SLOT(setRoomName(const QString &))); + ui.pageNetGame, SLOT(setRoomName(const QString &)), Qt::QueuedConnection); connect(hwnet, SIGNAL(chatStringFromNet(const QString&)), ui.pageNetGame->chatWidget, SLOT(onChatString(const QString&)), Qt::QueuedConnection); @@ -1731,6 +1731,7 @@ ui.pageNetGame->setMasterMode(true); ui.pageNetGame->restrictJoins->setChecked(false); ui.pageNetGame->restrictTeamAdds->setChecked(false); + ui.pageNetGame->restrictUnregistered->setChecked(false); ui.pageNetGame->pGameCFG->GameSchemes->setModel(ammoSchemeModel); ui.pageNetGame->pGameCFG->setMaster(true); ui.pageNetGame->pNetTeamsWidget->setInteractivity(true); @@ -1743,6 +1744,7 @@ ui.pageNetGame->leRoomName->disconnect(hwnet); ui.pageNetGame->restrictJoins->disconnect(hwnet); ui.pageNetGame->restrictTeamAdds->disconnect(hwnet); + ui.pageNetGame->restrictUnregistered->disconnect(hwnet); ui.pageNetGame->disconnect(hwnet, SLOT(updateRoomName(const QString&))); ui.pageNetGame->setRoomName(hwnet->getRoom()); @@ -1751,6 +1753,7 @@ connect(ui.pageNetGame, SIGNAL(askForUpdateRoomName(const QString &)), hwnet, SLOT(updateRoomName(const QString &))); connect(ui.pageNetGame->restrictJoins, SIGNAL(triggered()), hwnet, SLOT(toggleRestrictJoins())); connect(ui.pageNetGame->restrictTeamAdds, SIGNAL(triggered()), hwnet, SLOT(toggleRestrictTeamAdds())); + connect(ui.pageNetGame->restrictUnregistered, SIGNAL(triggered()), hwnet, SLOT(toggleRegisteredOnly())); connect(ui.pageNetGame->pGameCFG->GameSchemes->model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), ui.pageNetGame->pGameCFG, diff -r e96bf10216ef -r 9d1d0fa8db02 QTfrontend/net/newnetclient.cpp --- a/QTfrontend/net/newnetclient.cpp Mon Feb 25 19:48:35 2013 +0100 +++ b/QTfrontend/net/newnetclient.cpp Wed Feb 27 16:12:57 2013 +0100 @@ -63,6 +63,8 @@ connect(&NetSocket, SIGNAL(disconnected()), this, SLOT(OnDisconnect())); connect(&NetSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); + + connect(this, SIGNAL(messageProcessed()), this, SLOT(ClientRead()), Qt::QueuedConnection); } HWNewNet::~HWNewNet() @@ -186,6 +188,8 @@ { ParseCmd(cmdbuf); cmdbuf.clear(); + emit messageProcessed(); + return ; } else cmdbuf << s; @@ -486,9 +490,9 @@ emit connected(); } + m_playersModel->addPlayer(lst[i]); emit nickAddedLobby(lst[i], false); emit chatStringLobby(lst[i], tr("%1 *** %2 has joined").arg('\x03').arg("|nick|")); - m_playersModel->addPlayer(lst[i]); } return; } @@ -632,9 +636,9 @@ emit configAsked(); } + m_playersModel->playerJoinedRoom(lst[i]); emit nickAdded(lst[i], isChief && (lst[i] != mynick)); emit chatStringFromNet(tr("%1 *** %2 has joined the room").arg('\x03').arg(lst[i])); - m_playersModel->playerJoinedRoom(lst[i]); } return; } @@ -978,6 +982,11 @@ RawSendNet(QString("TOGGLE_RESTRICT_TEAMS")); } +void HWNewNet::toggleRegisteredOnly() +{ + RawSendNet(QString("TOGGLE_REGISTERED_ONLY")); +} + void HWNewNet::clearAccountsCache() { RawSendNet(QString("CLEAR_ACCOUNTS_CACHE")); diff -r e96bf10216ef -r 9d1d0fa8db02 QTfrontend/net/newnetclient.h --- a/QTfrontend/net/newnetclient.h Mon Feb 25 19:48:35 2013 +0100 +++ b/QTfrontend/net/newnetclient.h Wed Feb 27 16:12:57 2013 +0100 @@ -131,6 +131,8 @@ void setMyReadyStatus(bool isReady); + void messageProcessed(); + public slots: void ToggleReady(); void chatLineToNet(const QString& str); @@ -161,6 +163,7 @@ void startGame(); void toggleRestrictJoins(); void toggleRestrictTeamAdds(); + void toggleRegisteredOnly(); void partRoom(); void clearAccountsCache(); void getBanList(); diff -r e96bf10216ef -r 9d1d0fa8db02 QTfrontend/ui/page/pagenetgame.cpp --- a/QTfrontend/ui/page/pagenetgame.cpp Mon Feb 25 19:48:35 2013 +0100 +++ b/QTfrontend/ui/page/pagenetgame.cpp Wed Feb 27 16:12:57 2013 +0100 @@ -170,8 +170,11 @@ restrictJoins->setCheckable(true); restrictTeamAdds = new QAction(QAction::tr("Restrict Team Additions"), menu); restrictTeamAdds->setCheckable(true); + restrictUnregistered = new QAction(QAction::tr("Restrict Unregistered Players Join"), menu); + restrictUnregistered->setCheckable(true); menu->addAction(restrictJoins); menu->addAction(restrictTeamAdds); + menu->addAction(restrictUnregistered); BtnMaster->setMenu(menu); diff -r e96bf10216ef -r 9d1d0fa8db02 QTfrontend/ui/page/pagenetgame.h --- a/QTfrontend/ui/page/pagenetgame.h Mon Feb 25 19:48:35 2013 +0100 +++ b/QTfrontend/ui/page/pagenetgame.h Wed Feb 27 16:12:57 2013 +0100 @@ -49,6 +49,7 @@ QAction * restrictJoins; QAction * restrictTeamAdds; + QAction * restrictUnregistered; HWChatWidget* chatWidget; diff -r e96bf10216ef -r 9d1d0fa8db02 QTfrontend/ui/widget/themeprompt.cpp --- a/QTfrontend/ui/widget/themeprompt.cpp Mon Feb 25 19:48:35 2013 +0100 +++ b/QTfrontend/ui/widget/themeprompt.cpp Wed Feb 27 16:12:57 2013 +0100 @@ -162,4 +162,4 @@ { filterModel->setFilterFixedString(text); list->setCurrentIndex(filterModel->index(0, 0)); -} \ No newline at end of file +} diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/Actions.hs --- a/gameServer/Actions.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/Actions.hs Wed Feb 27 16:12:57 2013 +0100 @@ -32,68 +32,9 @@ import ConfigFile import EngineInteraction -data Action = - AnswerClients ![ClientChan] ![B.ByteString] - | SendServerMessage - | SendServerVars - | MoveToRoom RoomIndex - | MoveToLobby B.ByteString - | RemoveTeam B.ByteString - | SendTeamRemovalMessage B.ByteString - | RemoveRoom - | FinishGame - | UnreadyRoomClients - | JoinLobby - | ProtocolError B.ByteString - | Warning B.ByteString - | NoticeMessage Notice - | ByeClient B.ByteString - | KickClient ClientIndex - | KickRoomClient ClientIndex - | BanClient NominalDiffTime B.ByteString ClientIndex - | BanIP B.ByteString NominalDiffTime B.ByteString - | BanNick B.ByteString NominalDiffTime B.ByteString - | BanList - | Unban B.ByteString - | ChangeMaster (Maybe ClientIndex) - | RemoveClientTeams - | ModifyClient (ClientInfo -> ClientInfo) - | ModifyClient2 ClientIndex (ClientInfo -> ClientInfo) - | ModifyRoomClients (ClientInfo -> ClientInfo) - | ModifyRoom (RoomInfo -> RoomInfo) - | ModifyServerInfo (ServerInfo -> ServerInfo) - | AddRoom B.ByteString B.ByteString - | SendUpdateOnThisRoom - | CheckRegistered - | ClearAccountsCache - | ProcessAccountInfo AccountInfo - | AddClient ClientInfo - | DeleteClient ClientIndex - | PingAll - | StatsAction - | RestartServer - | AddNick2Bans B.ByteString B.ByteString UTCTime - | AddIP2Bans B.ByteString B.ByteString UTCTime - | CheckBanned Bool - | SaveReplay - | Stats - | CheckRecord - | CheckFailed B.ByteString - | CheckSuccess [B.ByteString] - type CmdHandler = [B.ByteString] -> Reader (ClientIndex, IRnC) [Action] -instance NFData Action where - rnf (AnswerClients chans msg) = chans `deepseq` msg `deepseq` () - rnf a = a `seq` () - -#if __GLASGOW_HASKELL__ < 706 -instance NFData B.ByteString -#endif - -instance NFData (Chan a) - othersChans :: StateT ServerState IO [ClientChan] othersChans = do @@ -461,8 +402,12 @@ when (not b) $ (if c then checkerLogin else playerLogin) passwd isAdmin Guest -> do b <- isBanned + c <- client's isChecker when (not b) $ - processAction JoinLobby + if c then + checkerLogin "" False + else + processAction JoinLobby Admin -> do mapM_ processAction [ModifyClient (\cl -> cl{isAdministrator = True}), JoinLobby] chan <- client's sendChan @@ -594,6 +539,7 @@ when (not $ ci `Set.member` rc) $ processAction $ ModifyServerInfo (\s -> s{bans = BanByIP ip reason expiring : bans s}) + processAction (CheckBanned byIP) = do clTime <- client's connectTime clNick <- client's nick @@ -613,6 +559,7 @@ getBanReason (BanByIP _ msg _) = msg getBanReason (BanByNick _ msg _) = msg + processAction PingAll = do rnc <- gets roomsClients io (allClientsM rnc) >>= mapM_ (kickTimeouted rnc) diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/CoreTypes.hs Wed Feb 27 16:12:57 2013 +0100 @@ -1,4 +1,4 @@ -{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-} +{-# LANGUAGE CPP, OverloadedStrings, DeriveDataTypeable #-} module CoreTypes where import Control.Concurrent @@ -12,9 +12,70 @@ import Control.Exception import Data.Typeable import Data.TConfig +import Control.DeepSeq ----------------------- import RoomsAndClients + +#if __GLASGOW_HASKELL__ < 706 +instance NFData B.ByteString +#endif + +instance NFData (Chan a) + +instance NFData Action where + rnf (AnswerClients chans msg) = chans `deepseq` msg `deepseq` () + rnf a = a `seq` () + +data Action = + AnswerClients ![ClientChan] ![B.ByteString] + | SendServerMessage + | SendServerVars + | MoveToRoom RoomIndex + | MoveToLobby B.ByteString + | RemoveTeam B.ByteString + | SendTeamRemovalMessage B.ByteString + | RemoveRoom + | FinishGame + | UnreadyRoomClients + | JoinLobby + | ProtocolError B.ByteString + | Warning B.ByteString + | NoticeMessage Notice + | ByeClient B.ByteString + | KickClient ClientIndex + | KickRoomClient ClientIndex + | BanClient NominalDiffTime B.ByteString ClientIndex + | BanIP B.ByteString NominalDiffTime B.ByteString + | BanNick B.ByteString NominalDiffTime B.ByteString + | BanList + | Unban B.ByteString + | ChangeMaster (Maybe ClientIndex) + | RemoveClientTeams + | ModifyClient (ClientInfo -> ClientInfo) + | ModifyClient2 ClientIndex (ClientInfo -> ClientInfo) + | ModifyRoomClients (ClientInfo -> ClientInfo) + | ModifyRoom (RoomInfo -> RoomInfo) + | ModifyServerInfo (ServerInfo -> ServerInfo) + | AddRoom B.ByteString B.ByteString + | SendUpdateOnThisRoom + | CheckRegistered + | ClearAccountsCache + | ProcessAccountInfo AccountInfo + | AddClient ClientInfo + | DeleteClient ClientIndex + | PingAll + | StatsAction + | RestartServer + | AddNick2Bans B.ByteString B.ByteString UTCTime + | AddIP2Bans B.ByteString B.ByteString UTCTime + | CheckBanned Bool + | SaveReplay + | Stats + | CheckRecord + | CheckFailed B.ByteString + | CheckSuccess [B.ByteString] + type ClientChan = Chan [B.ByteString] data CheckInfo = @@ -47,7 +108,8 @@ isKickedFromServer :: Bool, clientClan :: !(Maybe B.ByteString), checkInfo :: Maybe CheckInfo, - teamsInGame :: Word + teamsInGame :: Word, + actionsPending :: [Action] } instance Eq ClientInfo where diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/EngineInteraction.hs --- a/gameServer/EngineInteraction.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/EngineInteraction.hs Wed Feb 27 16:12:57 2013 +0100 @@ -90,10 +90,10 @@ initHealth = scheme !! 27 teamSetup :: TeamInfo -> [B.ByteString] teamSetup t = (++) ammo $ - eml ["eaddteam ", showB $ (1 + (readInt_ $ teamcolor t) :: Int) * 1234, " ", teamname t] + eml ["eaddteam ", showB $ (1 + (readInt_ $ teamcolor t) :: Int) * 2113696, " ", teamname t] : em "erdriven" : eml ["efort ", teamfort t] - : take (hhnum t) ( + : take (2 * hhnum t) ( concatMap (\(HedgehogInfo hname hhat) -> [ eml ["eaddhh ", showB $ difficulty t, " ", initHealth, " ", hname] , eml ["ehat ", hhat] diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/HWProtoCore.hs --- a/gameServer/HWProtoCore.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/HWProtoCore.hs Wed Feb 27 16:12:57 2013 +0100 @@ -30,12 +30,12 @@ handleCmd ["PONG"] = do cl <- thisClient if pingsQueue cl == 0 then - return [ProtocolError "Protocol violation"] + return $ actionsPending cl ++ [ModifyClient (\c -> c{actionsPending = []})] else return [ModifyClient (\c -> c{pingsQueue = pingsQueue c - 1})] -handleCmd ("CMD" : params) = - let c = concatMap B.words params in +handleCmd ("CMD" : parameters) = + let c = concatMap B.words parameters in if not $ null c then h $ (upperCase . head $ c) : tail c else @@ -45,6 +45,10 @@ h ["STATS"] = handleCmd ["STATS"] h ["PART", msg] = handleCmd ["PART", msg] h ["QUIT", msg] = handleCmd ["QUIT", msg] + h ["GLOBAL", msg] = do + rnc <- liftM snd ask + let chans = map (sendChan . client rnc) $ allClients rnc + return [AnswerClients chans ["CHAT", "[global notice]", msg]] h c = return [Warning . B.concat . L.intersperse " " $ "Unknown cmd" : c] handleCmd cmd = do diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/HWProtoInRoomState.hs --- a/gameServer/HWProtoInRoomState.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/HWProtoInRoomState.hs Wed Feb 27 16:12:57 2013 +0100 @@ -77,9 +77,12 @@ SendUpdateOnThisRoom, ModifyClient (\c -> c{teamsInGame = teamsInGame c + 1, clientClan = Just teamColor}), AnswerClients clChan ["TEAM_ACCEPTED", tName], - AnswerClients clChan ["HH_NUM", tName, showB $ hhnum newTeam], AnswerClients othChans $ teamToNet $ newTeam, - AnswerClients roomChans ["TEAM_COLOR", tName, teamColor] + AnswerClients roomChans ["TEAM_COLOR", tName, teamColor], + ModifyClient $ \c -> c{actionsPending = actionsPending cl + ++ [AnswerClients clChan ["HH_NUM", tName, showB $ hhnum newTeam]] + }, + AnswerClients [sendChan cl] ["PING"] ] where canAddNumber rt = (48::Int) - (sum $ map hhnum rt) @@ -226,7 +229,7 @@ (legalMsgs, nonEmptyMsgs) = checkNetCmd msg -handleCmd_inRoom ["ROUNDFINISHED", correctly] = do +handleCmd_inRoom ["ROUNDFINISHED", _] = do cl <- thisClient rm <- thisRoom chans <- roomClientsChans @@ -242,7 +245,7 @@ else return [] -- don't accept this message twice where - isCorrect = correctly == "1" +-- isCorrect = correctly == "1" -- compatibility with clients with protocol < 38 handleCmd_inRoom ["ROUNDFINISHED"] = diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/HWProtoLobbyState.hs --- a/gameServer/HWProtoLobbyState.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/HWProtoLobbyState.hs Wed Feb 27 16:12:57 2013 +0100 @@ -92,9 +92,12 @@ , AnswerClients [sendChan cl] $ ["CLIENT_FLAGS", "+h", ownerNick] ] ++ (if clientProto cl < 38 then map (readynessMessage cl) jRoomClients else [sendStateFlags cl jRoomClients]) - ++ answerFullConfig cl (mapParams jRoom) (params jRoom) - ++ answerTeams cl jRoom - ++ watchRound cl jRoom chans + ++ [AnswerClients [sendChan cl] ["PING"] + , ModifyClient $ \c -> c{actionsPending = actionsPending cl + ++ answerFullConfig cl (mapParams jRoom) (params jRoom) + ++ answerTeams cl jRoom + ++ watchRound cl jRoom chans} + ] where readynessMessage cl c = AnswerClients [sendChan cl] [if isReady c then "READY" else "NOT_READY", nick c] diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/NetRoutines.hs --- a/gameServer/NetRoutines.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/NetRoutines.hs Wed Feb 27 16:12:57 2013 +0100 @@ -47,6 +47,7 @@ Nothing Nothing 0 + [] ) writeChan chan $ Accept newClient diff -r e96bf10216ef -r 9d1d0fa8db02 gameServer/OfficialServer/checker.hs --- a/gameServer/OfficialServer/checker.hs Mon Feb 25 19:48:35 2013 +0100 +++ b/gameServer/OfficialServer/checker.hs Wed Feb 27 16:12:57 2013 +0100 @@ -32,10 +32,22 @@ serverAddress = "netserver.hedgewars.org" protocolNumber = "43" +getLines :: Handle -> IO [String] +getLines h = g + where + g = do + l <- liftM Just (hGetLine h) `Exception.catch` (\(_ :: Exception.IOException) -> return Nothing) + if isNothing l then + return [] + else + do + lst <- g + return $ fromJust l : lst + engineListener :: Chan Message -> Handle -> IO () engineListener coreChan h = do - output <- liftM lines $ hGetContents h + output <- getLines h debugM "Engine" $ show output if isNothing $ L.find start output then writeChan coreChan $ CheckFailed "No stats msg" diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/GSHandlers.inc --- a/hedgewars/GSHandlers.inc Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/GSHandlers.inc Wed Feb 27 16:12:57 2013 +0100 @@ -1783,7 +1783,7 @@ Gear^.Y := Gear^.Y + Gear^.dY; if (not Gear^.dY.isNegative) and (Gear^.dY > _0_001) then - SetAllHHToActive; + SetAllHHToActive(false); if (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) <> 0) then begin @@ -2382,7 +2382,9 @@ repeat CurrentTeam^.CurrHedgehog := Succ(CurrentTeam^.CurrHedgehog) mod (CurrentTeam^.HedgehogsNumber); - until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0); + until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and + (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear^.Damage = 0) and + (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Effects[heFrozen]=0); SwitchCurrentHedgehog(@CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog]); AmmoMenuInvalidated:= true; @@ -2876,6 +2878,7 @@ var t: PGearArray; ox, oy: hwFloat; + tempColl: Word; begin AllInactive := false; @@ -2894,11 +2897,12 @@ exit end end; - - if GameTicks > Gear^.FlightTime then + tempColl:= Gear^.CollisionMask; + Gear^.CollisionMask:= $007F; + if (TestCollisionYWithGear(Gear, hwSign(Gear^.dY)) <> 0) or TestCollisionXWithGear(Gear, hwSign(Gear^.dX)) or (GameTicks > Gear^.FlightTime) then t := CheckGearsCollision(Gear) - else t := nil; + Gear^.CollisionMask:= tempColl; //fixes drill not exploding when touching HH bug if (Gear^.Timer = 0) or ((t <> nil) and (t^.Count <> 0)) @@ -5042,7 +5046,138 @@ 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. *) + + +procedure updateFuel(Gear: PGear); +var + t:LongInt; +begin + t:= Gear^.Health div 10; + if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then + begin + Gear^.Damage:= t; + FreeTexture(Gear^.Tex); + Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(t) + + '%', cWhiteColor, fntSmall) + end; + if GameTicks mod 10 = 0 then dec(Gear^.Health); +end; + + +procedure updateTarget(Gear:PGear; newX, newY:HWFloat); + var + iter:PGear; +begin + with Gear^ do + begin + dX:= newX; + dY:= newY; + Pos:= 0; + Target.X:= NoPointX; + LastDamage:= nil; + X:= Hedgehog^.Gear^.X; + Y:= Hedgehog^.Gear^.Y; + //unfreeze all semifrozen hogs - make this generic hog cleanup +(* + iter := GearsList; + while iter <> nil do + begin + if (iter^.Kind = gtHedgehog) and + (iter^.Hedgehog^.Effects[heFrozen] and $FF = 0) then + iter^.Hedgehog^.Effects[heFrozen]:= 0; + iter:= iter^.NextGear + end +*) + end; +end; + + +function isLandscapeEdge(weight:Longint):boolean; +begin + result := (weight < 8) and (weight >= 2); +end; + +function isLandscape(weight:Longint):boolean; +begin + result := weight < 2; +end; + +function isEmptySpace(weight:Longint):boolean; +begin + result := not isLandscape(weight) and not isLandscapeEdge(weight); +end; + + +function getPixelWeight(x, y:Longint): Longint; +var + i, j:Longint; +begin + result := 0; + for i := x - 1 to x + 1 do + for j := y - 1 to y + 1 do + begin + if (i < 0) or + (i > LAND_WIDTH - 1) or + (j < 0) or + (j > LAND_HEIGHT -1) or + ((Land[j, i] and $FF00) = 0) then + begin + result := result + 1; + end; + end; +end; + + +procedure drawIcePixel(x, y:Longint); +var + iceSurface: PSDL_Surface; + icePixels: PLongwordArray; + pictureX, pictureY: LongInt; + w, c: LongWord; +begin + if Land[y, x] and lfIce <> 0 then exit; +// So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness + iceSurface:= SpritesData[sprIceTexture].Surface; + pictureX := x mod iceSurface^.w; + pictureY := y mod iceSurface^.h; + icePixels := iceSurface^.pixels; + w:= LandPixels[y, x]; + w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED + + (w shr BShift and $FF) * RGB_LUMINANCE_GREEN + + (w shr GShift and $FF) * RGB_LUMINANCE_BLUE)); + if w < 128 then w:= w+128; + if w > 255 then w:= 255; + w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixels[y,x] and AMask); + //LandPixels[y, x]:= w; + LandPixels[y, x]:= addBgColor(w, IceColor); + LandPixels[y, x]:= addBgColor(LandPixels[y, x], icePixels^[iceSurface^.w * (y mod iceSurface^.h) + (x mod iceSurface^.w)]); + + Land[y, x] := Land[y, x] or lfIce; +end; + +procedure DrawIce(x, y: Longint); + const iceRadius :Longint = 32; +var + i, j: Longint; + weight: Longint; + landRect : TSDL_RECT; +begin + FillRoundInLandWithIce(x, y, iceRadius); + SetAllHHToActive; + landRect.x := min(max(x - iceRadius, 0), LAND_WIDTH - 1); + landRect.y := min(max(y - iceRadius, 0), LAND_HEIGHT - 1); + landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1); + landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1); + UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true); +end; + + procedure doStepIceGun(Gear: PGear); +const iceWaitCollision:Longint = 0; +const iceCollideWithGround:Longint = 1; +const iceWaitNextTarget:Longint = 2; +const iceCollideWithHog:Longint = 4; +const groundFreezingTime:Longint = 1000; var HHGear: PGear; ndX, ndY: hwFloat; @@ -5050,7 +5185,7 @@ hogs: PGearArrayS; begin HHGear := Gear^.Hedgehog^.Gear; - if (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then + if (Gear^.Message and gmAttack <> 0) or (Gear^.Health = 0) or (HHGear = nil) or (HHGear^.Damage <> 0) then begin DeleteGear(Gear); AfterAttack; @@ -5058,16 +5193,9 @@ end else begin - t:= Gear^.Health div 10; - if (t <> Gear^.Damage) and ((GameTicks and $3F) = 0) then - begin - Gear^.Damage:= t; - FreeTexture(Gear^.Tex); - Gear^.Tex := RenderStringTex(trmsg[sidFuel] + ': ' + inttostr(t) + - '%', cWhiteColor, fntSmall) - end + updateFuel(Gear); end; - if GameTicks mod 10 = 0 then dec(Gear^.Health); + with Gear^ do begin HedgehogChAngle(HHGear); @@ -5077,65 +5205,76 @@ ((Target.X <> NoPointX) and (Target.X and LAND_WIDTH_MASK = 0) and (Target.Y and LAND_HEIGHT_MASK = 0) and ((Land[Target.Y, Target.X] = 0))) then begin - dX:= ndX; - dY:= ndY; - Pos:= 0; - Target.X:= NoPointX; - LastDamage:= nil; - X:= HHGear^.X; - Y:= HHGear^.Y; -(* unfreeze all semifrozen hogs - make this generic hog cleanup - iter := GearsList; - while iter <> nil do - begin - if (iter^.Kind = gtHedgehog) and - (iter^.Hedgehog^.Effects[heFrozen] < 0) then - iter^.Hedgehog^.Effects[heFrozen]:= 0; - iter:= iter^.NextGear - end *) + updateTarget(Gear, ndX, ndY); + IceState := iceWaitCollision; end else begin X:= X + dX; Y:= Y + dY; gX:= hwRound(X); - gY:= hwRound(Y); - if Target.X = NoPointX then t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y)); + gY:= hwRound(Y); + if Target.X = NoPointX then + begin + t:= hwRound(hwSqr(X-HHGear^.X)+hwSqr(Y-HHGear^.Y)); + end; + if Target.X <> NoPointX then - begin + begin + CheckCollisionWithLand(Gear); + if (State and gstCollision) <> 0 then + begin + if IceState = iceWaitCollision then + begin + IceState := iceCollideWithGround; + IceTime := GameTicks; + end; + end; + if (abs(gX-Target.X) < 2) and (abs(gY-Target.Y) < 2) then - begin + begin X:= HHGear^.X; Y:= HHGear^.Y - end; + end; + + if (IceState = iceCollideWithGround) and ((GameTicks - IceTime) > groundFreezingTime) then + begin + DrawIce(Target.X, Target.Y); + IceState := iceWaitNextTarget; + end; + // freeze nearby hogs - if GameTicks mod 10 = 0 then dec(Gear^.Health); - hogs := GearsNear(Gear^.X, Gear^.Y, gtHedgehog, Gear^.Radius); + hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2); if hogs.size > 0 then for i:= 0 to hogs.size - 1 do if hogs.ar^[i] <> HHGear then - begin - //if Gear^.Hedgehog^.Effects[heFrozen]:= 0; - end; + if GameTicks mod 5 = 0 then + begin + hogs.ar^[i]^.Active:= true; + if hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] < 256 then + hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] := hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] + 1 + else if hogs.ar^[i]^.Hedgehog^.Effects[heFrozen] = 256 then + hogs.ar^[i]^.Hedgehog^.Effects[heFrozen]:= 100000 + end; inc(Pos) - end + end else if (t > 400) and ((gY > cWaterLine) or (((gX and LAND_WIDTH_MASK = 0) and (gY and LAND_HEIGHT_MASK = 0)) and (Land[gY, gX] <> 0))) then - begin + begin Target.X:= gX; Target.Y:= gY; X:= HHGear^.X; Y:= HHGear^.Y - end; - if (gX > max(LAND_WIDTH,4096)*2) or + end; + {if (gX > max(LAND_WIDTH,4096)*2) or (gX < -max(LAND_WIDTH,4096)) or (gY < -max(LAND_HEIGHT,4096)) or (gY > max(LAND_HEIGHT,4096)+512) then - begin + begin X:= HHGear^.X; Y:= HHGear^.Y - end + end} end end; end; diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uChat.pas --- a/hedgewars/uChat.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uChat.pas Wed Feb 27 16:12:57 2013 +0100 @@ -394,9 +394,7 @@ SetLine(InputStr, '', true) else begin - // err, does anyone have any documentation on this sequence? - // ^^ isn't it obvious? 27 is esc, 32 is space, inbetween is "/team" - KeyPressChat(27); + // "/team " KeyPressChat(47); KeyPressChat(116); KeyPressChat(101); diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uCommandHandlers.pas --- a/hedgewars/uCommandHandlers.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uCommandHandlers.pas Wed Feb 27 16:12:57 2013 +0100 @@ -594,7 +594,6 @@ if bShowAmmoMenu then bShowAmmoMenu:= false else if not(CurrentTeam^.Extdriven) and (((Gear^.State and (gstAttacking or gstAttacked)) <> 0) - or ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0)) or ((Gear^.State and gstHHDriven) = 0)) then begin end diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uGears.pas --- a/hedgewars/uGears.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uGears.pas Wed Feb 27 16:12:57 2013 +0100 @@ -46,7 +46,8 @@ procedure ProcessGears; procedure EndTurnCleanup; procedure SetAllToActive; -procedure SetAllHHToActive; +procedure SetAllHHToActive; inline; +procedure SetAllHHToActive(Ice: boolean); procedure DrawGears; procedure FreeGearsList; procedure AddMiscGears; @@ -442,7 +443,8 @@ if TurnTimeLeft > 0 then if CurrentHedgehog^.Gear <> nil then - if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) then + if ((CurrentHedgehog^.Gear^.State and gstAttacking) = 0) and + not(isInMultiShoot and (CurrentHedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle])) then begin if (TurnTimeLeft = 5000) and (cHedgehogTurnTime >= 10000) @@ -561,7 +563,12 @@ end end; -procedure SetAllHHToActive; +procedure SetAllHHToActive; inline; +begin +SetAllHHToActive(true) +end; + +procedure SetAllHHToActive(Ice: boolean); var t: PGear; begin AllInactive:= false; @@ -569,12 +576,14 @@ while t <> nil do begin if (t^.Kind = gtHedgehog) or (t^.Kind = gtExplosives) then - t^.Active:= true; + begin + if (t^.Kind = gtHedgehog) and Ice then CheckIce(t); + t^.Active:= true + end; t:= t^.NextGear end end; - procedure DrawGears; var Gear: PGear; x, y: LongInt; @@ -765,6 +774,8 @@ begin dec(i); Gear:= t^.ar[i]; + if (Ammo^.Kind = gtFlame) and (Gear^.Kind = gtHedgehog) and (Gear^.Hedgehog^.Effects[heFrozen] > 255) then + Gear^.Hedgehog^.Effects[heFrozen]:= max(255,Gear^.Hedgehog^.Effects[heFrozen]-10000); tmpDmg:= ModifyDamage(Damage, Gear); if (Gear^.State and gstNoDamage) = 0 then begin @@ -779,6 +790,7 @@ if (Gear^.Kind = gtHedgehog) and (Ammo^.State and gsttmpFlag <> 0) and (Ammo^.Kind = gtShover) then Gear^.FlightTime:= 1; + case Gear^.Kind of gtHedgehog, gtMine, diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uGearsHedgehog.pas --- a/hedgewars/uGearsHedgehog.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uGearsHedgehog.pas Wed Feb 27 16:12:57 2013 +0100 @@ -29,6 +29,7 @@ procedure HedgehogChAngle(HHGear: PGear); procedure PickUp(HH, Gear: PGear); procedure AddPickup(HH: THedgehog; ammo: TAmmoType; cnt, X, Y: LongWord); +procedure CheckIce(Gear: PGear); inline; implementation uses uConsts, uVariables, uFloat, uAmmos, uSound, uCaptions, @@ -53,7 +54,6 @@ prevAmmo:= CurAmmoType; ammoidx:= 0; if ((HHGear^.State and (gstAttacking or gstAttacked)) <> 0) - or ((MultiShootAttacks > 0) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) = 0)) or ((HHGear^.State and gstHHDriven) = 0) then exit; ChangeAmmo:= true; @@ -61,8 +61,12 @@ while (ammoidx < cMaxSlotAmmoIndex) and (Ammo^[slot, ammoidx].AmmoType <> CurAmmoType) do inc(ammoidx); - if ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_NoRoundEnd) <> 0) and (MultiShootAttacks > 0) then - OnUsedAmmo(HHGear^.Hedgehog^); + if (MultiShootAttacks > 0) then + begin + if (CurAmmoType = amSniperRifle) and ((GameFlags and gfArtillery) = 0) then + cArtillery := false; + OnUsedAmmo(HHGear^.Hedgehog^) + end; MultiShootAttacks:= 0; HHGear^.Message:= HHGear^.Message and (not (gmLJump or gmHJump)); @@ -374,7 +378,10 @@ end; //amStructure: newGear:= AddGear(hwRound(lx) + hwSign(dX) * 7, hwRound(ly), gtStructure, gstWait, SignAs(_0_02, dX), _0, 3000); amTardis: newGear:= AddGear(hwRound(X), hwRound(Y), gtTardis, 0, _0, _0, 5000); - amIceGun: newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0); + amIceGun: begin + newGear:= AddGear(hwRound(X), hwRound(Y), gtIceGun, 0, _0, _0, 0); + newGear^.radius := 8; + end; end; if altUse and (newGear <> nil) then begin @@ -455,7 +462,7 @@ if (CurAmmoGear <> nil) and ((Ammoz[CurAmmoType].Ammo.Propz and ammoprop_AltUse) = 0){check for dropping ammo from rope} then begin - if CurAmmoType = amRope then Message:= Message or gmAttack; + if CurAmmoType in [amRope,amResurrector] then Message:= Message or gmAttack; CurAmmoGear^.Message:= Message end else @@ -775,7 +782,7 @@ if (not cArtillery) and ((Gear^.Message and gmPrecise) = 0) then MakeHedgehogsStep(Gear); - SetAllHHToActive; + SetAllHHToActive(false); AddGearCI(Gear) end end; @@ -998,20 +1005,13 @@ Hedgehog: PHedgehog; begin Hedgehog:= HHGear^.Hedgehog; -// Some weapons, deagle in particular, wouldn't play so nice in infinite attack mode if hogs were still moving. Most likely scenario -// is trying to shoot them twice while rolling. This is mostly about not wasting ammo, but shouldn't apply to gears not using AmmoShove (portal -// Should we rethink AmmoShove? Presumably we'd need a way of knowing if current gear had already attacked a gear -if isInMultiShoot and not AllInactive and (Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]) then HHGear^.Message:= HHGear^.Message and not gmAttack; -(* -if isInMultiShoot then - HHGear^.Message:= 0; -*) - -(*if ((Ammoz[CurrentHedgehog^.CurAmmoType].Ammo.Propz and ammoprop_Utility) <> 0) and isInMultiShoot then - AllInactive:= true -else if not isInMultiShoot then - AllInactive:= false;*) - AllInactive:= false; +//if isInMultiShoot and not AllInactive and (Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]) then HHGear^.Message:= HHGear^.Message and not gmAttack; +if isInMultiShoot and (Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle]) then + begin + AllInactive:= true; + HHGear^.Message:= 0 + end +else AllInactive:= false; if (TurnTimeLeft = 0) or (HHGear^.Damage > 0) then begin @@ -1128,7 +1128,7 @@ exit end; - if Hedgehog^.Gear <> nil then + if not(isInMultiShoot and (Hedgehog^.CurAmmoType in [amShotgun, amDEagle, amSniperRifle])) and (Hedgehog^.Gear <> nil) then begin if GHStepTicks > 0 then dec(GHStepTicks); @@ -1200,7 +1200,7 @@ if Gear^.Timer = 0 then begin Gear^.State:= Gear^.State and (not (gstWait or gstLoser or gstWinner or gstAttacked or gstNotKickable or gstHHChooseTarget)); - Gear^.Active:= false; + if Gear^.Hedgehog^.Effects[heFrozen] = 0 then Gear^.Active:= false; AddGearCI(Gear); exit end @@ -1210,40 +1210,24 @@ AllInactive:= false end; -//////////////////////////////////////////////////////////////////////////////// -procedure doStepHedgehog(Gear: PGear); +procedure CheckIce(Gear: PGear); inline; (* var x,y,tx,ty: LongInt; tdX, tdY, slope: hwFloat; land: Word; *) var slope: hwFloat; begin -CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel; -if (Gear^.Message and gmDestroy) <> 0 then - begin - DeleteGear(Gear); - exit - end; - -if (Gear^.State and gstHHDriven) = 0 then - doStepHedgehogFree(Gear) -else - begin - with Gear^.Hedgehog^ do - if Team^.hasGone then - TeamGoneEffect(Team^) - else - doStepHedgehogDriven(Gear) - end; -if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0) -and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0) -and (not Gear^.dY.isNegative) and (GameTicks mod (100*LongWOrd(hwRound(cMaxWindSpeed*2/cGravity))) = 0) -and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then - begin - slope:= CalcSlopeBelowGear(Gear); - Gear^.dX:=Gear^.dX+slope*_0_07; - if slope.QWordValue <> 0 then - Gear^.State:= Gear^.State or gstMoving; + if (Gear^.Message and (gmAllStoppable or gmLJump or gmHJump) = 0) + and (Gear^.State and (gstHHJumping or gstHHHJump or gstAttacking) = 0) + and (not Gear^.dY.isNegative) and (TestCollisionYwithGear(Gear, 1) and lfIce <> 0) then + begin + slope:= CalcSlopeBelowGear(Gear); + if slope.QWordValue > 730144440 then // ignore mild slopes + begin + Gear^.dX:=Gear^.dX+slope*cGravity*_256; + Gear^.State:= Gear^.State or gstMoving + end + end; (* x:= hwRound(Gear^.X); y:= hwRound(Gear^.Y); @@ -1258,7 +1242,35 @@ AddVisualGear(x + hwRound(_40 * slope), y - hwRound(_40 * slope), vgtSmokeTrace); AddVisualGear(x - hwRound(_50 * slope), y + hwRound(_50 * slope), vgtSmokeTrace); AddVisualGear(x + hwRound(_50 * slope), y - hwRound(_50 * slope), vgtSmokeTrace); *) - end +end; + +//////////////////////////////////////////////////////////////////////////////// +procedure doStepHedgehog(Gear: PGear); +begin +CheckSum:= CheckSum xor Gear^.Hedgehog^.BotLevel; +if (Gear^.Message and gmDestroy) <> 0 then + begin + DeleteGear(Gear); + exit + end; +if GameTicks mod 100 = 0 then CheckIce(Gear); +if Gear^.Hedgehog^.Effects[heFrozen] > 0 then + begin + if Gear^.Hedgehog^.Effects[heFrozen] > 256 then + dec(Gear^.Hedgehog^.Effects[heFrozen]) + else if GameTicks mod 10 = 0 then + dec(Gear^.Hedgehog^.Effects[heFrozen]) + end; +if (Gear^.State and gstHHDriven) = 0 then + doStepHedgehogFree(Gear) +else + begin + with Gear^.Hedgehog^ do + if Team^.hasGone then + TeamGoneEffect(Team^) + else + doStepHedgehogDriven(Gear) + end; end; end. diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uGearsRender.pas --- a/hedgewars/uGearsRender.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uGearsRender.pas Wed Feb 27 16:12:57 2013 +0100 @@ -211,6 +211,8 @@ defaultPos, HatVisible: boolean; HH: PHedgehog; CurWeapon: PAmmo; + iceOffset:Longint; + r:TSDL_Rect; begin HH:= Gear^.Hedgehog; if HH^.Unplaced then @@ -239,6 +241,29 @@ defaultPos:= true; HatVisible:= false; + if HH^.Effects[heFrozen] > 0 then + if HH^.Effects[heFrozen] < 256 then + begin + DrawHedgehog(sx, sy, + sign, + 0, + 0, + 0); + defaultPos:= false; + HatVisible:= true + end + else + begin + DrawHedgehog(sx, sy, + sign, + 2, + 4, + 0); + defaultPos:= false; + HatVisible:= false; + exit + end; + if HH^.Effects[hePoisoned] <> 0 then begin @@ -247,6 +272,7 @@ Tint($FF, $FF, $FF, $FF) end; + if ((Gear^.State and gstWinner) <> 0) and ((CurAmmoGear = nil) or (CurAmmoGear^.Kind <> gtPickHammer)) then begin @@ -538,7 +564,7 @@ DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex) end; gtIceGun: - begin DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle); + begin DrawSpriteRotated(sprIceGun, hx, hy, sign, aangle); if CurAmmoGear^.Tex <> nil then DrawTextureCentered(sx, sy - 40, CurAmmoGear^.Tex) end; @@ -669,7 +695,7 @@ amBee: DrawSpriteRotatedF(sprHandBee, hx, hy, (RealTicks div 125) mod 4, sign, aangle); amFlamethrower: DrawSpriteRotatedF(sprHandFlamethrower, hx, hy, (RealTicks div 125) mod 4, sign, aangle); amLandGun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle); - amIceGun: DrawSpriteRotated(sprHandBallgun, hx, hy, sign, aangle); + amIceGun: DrawSpriteRotated(sprIceGun, hx, hy, sign, aangle); amResurrector: DrawCircle(ox, oy, 98, 4, $F5, $DB, $35, $AA); // I'd rather not like to hardcode 100 here end; @@ -917,6 +943,23 @@ Tint($FF, $FF, $FF, max($40, round($FF * abs(1 - ((RealTicks div 2 + Gear^.uid * 491) mod 1500) / 750)))); DrawSprite(sprInvulnerable, sx - 24, sy - 24, 0); end; + + if HH^.Effects[heFrozen] = HH^.Effects[heFrozen] and $FF then + begin + /// Tint($00, $FF, $40, $40); (HH^.Effects[heFrozen] and $FF) + iceOffset:= trunc(HH^.Effects[heFrozen] / 256 * 64); + Tint($FF, $FF, $FF, $FF); + r.x := 128; + r.y := 128 - iceOffset; + r.w := 64; + r.h := iceOffset; + //DrawTextureFromRect(sx-32, sy-iceoffset+32, @r, SpritesData[sprFrozenHog].texture); + DrawTextureFromRectDir(sx-16+sign*2, sy+48-iceoffset, r.w, r.h, @r, HHTexture, sign); + + Tint($FF, $FF, $FF, $FF); + end; + + if cVampiric and (CurrentHedgehog^.Gear <> nil) and (CurrentHedgehog^.Gear = Gear) then diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uGearsUtils.pas --- a/hedgewars/uGearsUtils.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uGearsUtils.pas Wed Feb 27 16:12:57 2013 +0100 @@ -182,6 +182,7 @@ i:= _1; if (CurrentHedgehog <> nil) and CurrentHedgehog^.King then i:= _1_5; +if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.Effects[heFrozen] > 0) then i:=i*_0_2; if (Gear^.Hedgehog <> nil) and (Gear^.Hedgehog^.King) then ModifyDamage:= hwRound(_0_01 * cDamageModifier * dmg * i * cDamagePercent * _0_5) else diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uIO.pas --- a/hedgewars/uIO.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uIO.pas Wed Feb 27 16:12:57 2013 +0100 @@ -249,7 +249,10 @@ flushBuffer(); Move(s, sendBuffer.buf[sendBuffer.count], byte(s[0]) + 1); - inc(sendBuffer.count, byte(s[0]) + 1) + inc(sendBuffer.count, byte(s[0]) + 1); + + if (s[1] = 'N') or (s[1] = '#') then + flushBuffer(); end else SDLNet_TCP_Send(IPCSock, @s, Succ(byte(s[0]))) end diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uLandGraphics.pas --- a/hedgewars/uLandGraphics.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uLandGraphics.pas Wed Feb 27 16:12:57 2013 +0100 @@ -36,6 +36,7 @@ procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte); procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt); procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword); +procedure FillRoundInLandWithIce(X, Y, Radius: LongInt); procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean); function LandBackPixel(x, y: LongInt): LongWord; procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword); @@ -158,6 +159,8 @@ end end; + + procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword); var dx, dy, d: LongInt; begin @@ -243,6 +246,130 @@ end; + +function isLandscapeEdge(weight:Longint):boolean; +begin + result := (weight < 8) and (weight >= 2); +end; + +function isLandscape(weight:Longint):boolean; +begin + result := weight < 2; +end; + +function isEmptySpace(weight:Longint):boolean; +begin + result := not isLandscape(weight) and not isLandscapeEdge(weight); +end; + +function getPixelWeight(x, y:Longint): Longint; +var + i, j:Longint; +begin + result := 0; + for i := x - 1 to x + 1 do + for j := y - 1 to y + 1 do + begin + if (i < 0) or + (i > LAND_WIDTH - 1) or + (j < 0) or + (j > LAND_HEIGHT -1) or + ((Land[j, i] and $FF00) = 0) then + begin + result := result + 1; + end; + end; +end; + +procedure drawIcePixel(y, x:Longint); +var + iceSurface: PSDL_Surface; + icePixels: PLongwordArray; + pictureX, pictureY: LongInt; + w, c: LongWord; + weight: Longint; +begin + weight := getPixelWeight(x, y); + if isLandscape(weight) then + begin + // So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness + iceSurface:= SpritesData[sprIceTexture].Surface; + pictureX := x mod iceSurface^.w; + pictureY := y mod iceSurface^.h; + icePixels := iceSurface^.pixels; + w:= LandPixels[y, x]; + w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED + + (w shr BShift and $FF) * RGB_LUMINANCE_GREEN + + (w shr GShift and $FF) * RGB_LUMINANCE_BLUE)); + if w < 128 then w:= w+128; + if w > 255 then w:= 255; + w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixels[y,x] and AMask); + //LandPixels[y, x]:= w; + LandPixels[y, x]:= addBgColor(w, IceColor); + LandPixels[y, x]:= addBgColor(LandPixels[y, x], icePixels^[iceSurface^.w * (y mod iceSurface^.h) + (x mod iceSurface^.w)]); + Land[y, x] := land[y, x] or lfIce; + end + else if (isLandscapeEdge(weight)) then + begin + LandPixels[y, x] := $FFB2AF8A; + if Land[y, x] > 255 then Land[y, x] := Land[y, x] or lfIce; + end; + +end; + +function getIncrementInquarter(dx, dy, quarter: Longint): Longint; +const directionX : array [0..3] of Longint = (0, 0, 1, -1); +const directionY : array [0..3] of Longint = (1, -1, 0, 0); +begin + getIncrementInquarter := directionX[quarter] * dx + directionY[quarter] * dy; +end; + +function getIncrementInquarter2(dx, dy, quarter: Longint): Longint; +const directionY : array [0..3] of Longint = (0, 0, 1, 1); +const directionX : array [0..3] of Longint = (1, 1, 0, 0); +begin + getIncrementInquarter2 := directionX[quarter] * dx + directionY[quarter] * dy; +end; + +procedure FillLandCircleLinesIce(x, y, dx, dy: LongInt); +var q, i, t: LongInt; +begin +for q := 0 to 3 do + begin + t:= y + getIncrementInquarter(dx, dy, q); + if (t and LAND_HEIGHT_MASK) = 0 then + for i:= Max(x - getIncrementInquarter2(dx, dy, q), 0) to Min(x + getIncrementInquarter2(dx, dy, q), LAND_WIDTH - 1) do + if (Land[t, i] and (lfIndestructible or lfIce) = 0) and (not disableLandBack or (Land[t, i] > 255)) then + if (cReducedQuality and rqBlurryLand) = 0 then + drawIcePixel(t, i) + else + drawIcePixel(t div 2, i div 2) ; + end; +end; + +procedure FillRoundInLandWithIce(X, Y, Radius: LongInt); +var dx, dy, d: LongInt; +begin +dx:= 0; +dy:= Radius; +d:= 3 - 2 * Radius; + while (dx < dy) do + begin + FillLandCircleLinesIce(x, y, dx, dy); + if (d < 0) then + d:= d + 4 * dx + 6 + else + begin + d:= d + 4 * (dx - dy) + 10; + dec(dy) + end; + inc(dx) + end; + if (dx = dy) then + FillLandCircleLinesIce(x, y, dx, dy); +end; + + function FillLandCircleLinesBG(x, y, dx, dy: LongInt): Longword; var i, t, by, bx: LongInt; cnt: Longword; @@ -350,7 +477,7 @@ else LandPixels[t div 2, i div 2]:= ExplosionBorderColor; - Land[t, i]:= Land[t, i] or lfDamaged; + Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce; //Despeckle(i, t); LandDirty[t div 32, i div 32]:= 1; end; @@ -364,7 +491,7 @@ LandPixels[t, i]:= ExplosionBorderColor else LandPixels[t div 2, i div 2]:= ExplosionBorderColor; - Land[t, i]:= Land[t, i] or lfDamaged; + Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce; //Despeckle(i, t); LandDirty[t div 32, i div 32]:= 1; end; @@ -379,7 +506,7 @@ else LandPixels[t div 2, i div 2]:= ExplosionBorderColor; - Land[t, i]:= Land[t, i] or lfDamaged; + Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce; //Despeckle(i, t); LandDirty[t div 32, i div 32]:= 1; end; @@ -394,7 +521,7 @@ else LandPixels[t div 2, i div 2]:= ExplosionBorderColor; - Land[t, i]:= Land[t, i] or lfDamaged; + Land[t, i]:= (Land[t, i] or lfDamaged) and not lfIce; //Despeckle(i, y - dy); LandDirty[t div 32, i div 32]:= 1; end; @@ -525,7 +652,7 @@ else LandPixels[ty div 2, tx div 2]:= ExplosionBorderColor; - Land[ty, tx]:= Land[ty, tx] or lfDamaged; + Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce; LandDirty[ty div 32, tx div 32]:= 1; end; inc(y, dY) @@ -567,6 +694,7 @@ and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin + Land[ty, tx]:= Land[ty, tx] and not lfIce; if despeckle then begin Land[ty, tx]:= Land[ty, tx] or lfDamaged; @@ -595,7 +723,7 @@ if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - Land[ty, tx]:= Land[ty, tx] or lfDamaged; + Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce; if despeckle then LandDirty[ty div 32, tx div 32]:= 1; if (cReducedQuality and rqBlurryLand) = 0 then @@ -638,7 +766,7 @@ if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - Land[ty, tx]:= Land[ty, tx] or lfDamaged; + Land[ty, tx]:=( Land[ty, tx] or lfDamaged) and not lfIce; if despeckle then LandDirty[ty div 32, tx div 32]:= 1; if (cReducedQuality and rqBlurryLand) = 0 then @@ -664,7 +792,7 @@ if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) and (((Land[ty, tx] and lfBasic) <> 0) or ((Land[ty, tx] and lfObject) <> 0)) then begin - Land[ty, tx]:= Land[ty, tx] or lfDamaged; + Land[ty, tx]:= (Land[ty, tx] or lfDamaged) and not lfIce; if despeckle then LandDirty[ty div 32, tx div 32]:= 1; if (cReducedQuality and rqBlurryLand) = 0 then diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uRender.pas --- a/hedgewars/uRender.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uRender.pas Wed Feb 27 16:12:57 2013 +0100 @@ -26,15 +26,16 @@ procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt); procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt); -procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); +procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline; procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt); procedure DrawSpriteRotated (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real); procedure DrawSpriteRotatedF (Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real); procedure DrawTexture (X, Y: LongInt; Texture: PTexture); inline; procedure DrawTexture (X, Y: LongInt; Texture: PTexture; Scale: GLfloat); -procedure DrawTextureFromRect (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); -procedure DrawTextureFromRect (X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); +procedure DrawTextureFromRect (X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; +procedure DrawTextureFromRect (X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; +procedure DrawTextureFromRectDir(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture; Dir: LongInt); procedure DrawTextureCentered (X, Top: LongInt; Source: PTexture); procedure DrawTextureF (Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt); procedure DrawTextureRotated (Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real); @@ -63,19 +64,23 @@ var LastTint: LongWord = 0; -procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); +procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt); inline; begin r.y:= r.y + Height * Position; r.h:= Height; DrawTextureFromRect(X, Y, @r, SpritesData[Sprite].Texture) end; -procedure DrawTextureFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); +procedure DrawTextureFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; begin -DrawTextureFromRect(X, Y, r^.w, r^.h, r, SourceTexture) +DrawTextureFromRectDir(X, Y, r^.w, r^.h, r, SourceTexture, 1) +end; +procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); inline; +begin +DrawTextureFromRectDir(X, Y, W, H, r, SourceTexture, 1) end; -procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture); +procedure DrawTextureFromRectDir(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture; Dir: LongInt); var rr: TSDL_Rect; _l, _r, _t, _b: real; VertexBuffer, TextureBuffer: array [0..3] of TVertex2f; @@ -101,14 +106,28 @@ glBindTexture(GL_TEXTURE_2D, SourceTexture^.id); -VertexBuffer[0].X:= X; -VertexBuffer[0].Y:= Y; -VertexBuffer[1].X:= rr.w + X; -VertexBuffer[1].Y:= Y; -VertexBuffer[2].X:= rr.w + X; -VertexBuffer[2].Y:= rr.h + Y; -VertexBuffer[3].X:= X; -VertexBuffer[3].Y:= rr.h + Y; +if Dir < 0 then + begin + VertexBuffer[0].X:= X + rr.w/2; + VertexBuffer[0].Y:= Y; + VertexBuffer[1].X:= X - rr.w/2; + VertexBuffer[1].Y:= Y; + VertexBuffer[2].X:= X - rr.w/2; + VertexBuffer[2].Y:= rr.h + Y; + VertexBuffer[3].X:= X + rr.w/2; + VertexBuffer[3].Y:= rr.h + Y; + end +else + begin + VertexBuffer[0].X:= X; + VertexBuffer[0].Y:= Y; + VertexBuffer[1].X:= rr.w + X; + VertexBuffer[1].Y:= Y; + VertexBuffer[2].X:= rr.w + X; + VertexBuffer[2].Y:= rr.h + Y; + VertexBuffer[3].X:= X; + VertexBuffer[3].Y:= rr.h + Y; + end; TextureBuffer[0].X:= _l; TextureBuffer[0].Y:= _t; diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uTeams.pas --- a/hedgewars/uTeams.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uTeams.pas Wed Feb 27 16:12:57 2013 +0100 @@ -188,11 +188,11 @@ PrevHH:= CurrHedgehog mod HedgehogsNumber; // prevent infinite loop when CurrHedgehog = 7, but HedgehogsNumber < 8 (team is destroyed before its first turn) repeat CurrHedgehog:= Succ(CurrHedgehog) mod HedgehogsNumber; - until (Hedgehogs[CurrHedgehog].Gear <> nil) or (CurrHedgehog = PrevHH) + until ((Hedgehogs[CurrHedgehog].Gear <> nil) and (Hedgehogs[CurrHedgehog].Effects[heFrozen] = 0)) or (CurrHedgehog = PrevHH) end until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) or (PrevTeam = CurrTeam) or ((CurrTeam = TagTeamIndex) and ((GameFlags and gfTagTeam) <> 0)); end -until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil); +until (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Gear <> nil) and (CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog].Effects[heFrozen] = 0); SwitchCurrentHedgehog(@(CurrentTeam^.Hedgehogs[CurrentTeam^.CurrHedgehog])); {$IFDEF USE_TOUCH_INTERFACE} diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uTypes.pas --- a/hedgewars/uTypes.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uTypes.pas Wed Feb 27 16:12:57 2013 +0100 @@ -86,7 +86,7 @@ sprHandResurrector, sprCross, sprAirDrill, sprNapalmBomb, sprBulletHit, sprSnowball, sprHandSnowball, sprSnow, sprSDFlake, sprSDWater, sprSDCloud, sprSDSplash, sprSDDroplet, sprTardis, - sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar + sprSlider, sprBotlevels, sprHandKnife, sprKnife, sprStar, sprIceTexture, sprIceGun, sprFrozenHog ); // Gears that interact with other Gears and/or Land @@ -259,6 +259,8 @@ SoundChannel: LongInt; PortalCounter: LongWord; // Hopefully temporary, but avoids infinite portal loops in a guaranteed fashion. AIHints: LongWord; // hints for ai. haha ^^^^^^ temporary, sure + IceTime: Longint; //time of ice beam with object some interaction temporary + IceState: Longint; //state of ice gun temporary LastDamage: PHedgehog; end; TPGearArray = array of PGear; diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uUtils.pas --- a/hedgewars/uUtils.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uUtils.pas Wed Feb 27 16:12:57 2013 +0100 @@ -361,14 +361,14 @@ if (#$1100 <= u) and ( (u <= #$11FF ) or // Hangul Jamo ((#$2E80 <= u) and (u <= #$2FDF)) or // CJK Radicals Supplement / Kangxi Radicals - ((#$2FF0 <= u) and (u <= #$303F)) or // Ideographic Description Characters / CJK Radicals Supplement - ((#$3130 <= u) and (u <= #$318F)) or // Hangul Compatibility Jamo + ((#$2FF0 <= u) and (u <= #$31FF)) or // Ideographic Description Characters / CJK Radicals Supplement / Hiragana / Hangul Compatibility Jamo / Katakana ((#$31C0 <= u) and (u <= #$31EF)) or // CJK Strokes - ((#$3200 <= u) and (u <= #$4DBF)) or // Enclosed CJK Letters and Months / CJK Compatibility / CJK Unified Ideographs Extension A + ((#$3200 <= u) and (u <= #$4DBF)) or // Enclosed CJK Letters and Months / CJK Compatibility / CJK Unified Ideographs Extension A / Circled Katakana ((#$4E00 <= u) and (u <= #$9FFF)) or // CJK Unified Ideographs ((#$AC00 <= u) and (u <= #$D7AF)) or // Hangul Syllables ((#$F900 <= u) and (u <= #$FAFF)) or // CJK Compatibility Ideographs - ((#$FE30 <= u) and (u <= #$FE4F))) // CJK Compatibility Forms + ((#$FE30 <= u) and (u <= #$FE4F)) or // CJK Compatibility Forms + ((#$FF66 <= u) and (u <= #$FF9D))) // halfwidth katakana then begin CheckCJKFont:= THWFont( ord(font) + ((ord(High(THWFont))+1) div 2) ); diff -r e96bf10216ef -r 9d1d0fa8db02 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Mon Feb 25 19:48:35 2013 +0100 +++ b/hedgewars/uVariables.pas Wed Feb 27 16:12:57 2013 +0100 @@ -115,6 +115,7 @@ // originally typed consts ExplosionBorderColor: LongWord; + IceColor : LongWord; WaterOpacity: byte; SDWaterOpacity: byte; GrayScale: Boolean; @@ -654,16 +655,18 @@ Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprSlider (FileName: 'botlevels'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; Width: 22; Height: 15; imageWidth: 22; imageHeight: 15; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprBotlevels - (* (FileName: 'amKnife'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandKnife*) (FileName: 'amCleaver'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil; Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: false),// sprHandKnife - (*(FileName: 'knife'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 29; Height: 14; imageWidth: 64; imageHeight: 64; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprKnife*) (FileName: 'cleaver'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; Width: 64; Height: 64; imageWidth: 64; imageHeight: 128; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprKnife (FileName: 'star'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; - Width: 12; Height: 12; imageWidth: 12; imageHeight: 12; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprStar + Width: 12; Height: 12; imageWidth: 12; imageHeight: 12; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprStar + (FileName: 'icetexture'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 128; Height: 128; imageWidth: 128; imageHeight: 128; saveSurf: true; priority: tpLow; getDimensions: false; getImageDimensions: true), // sprIceTexture + (FileName: 'amIceGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 32; Height: 32; imageWidth: 32; imageHeight: 32; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false), // sprIceGun + (FileName: 'amFrozenHog'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil; + Width: 64; Height: 64; imageWidth: 64; imageHeight: 64; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprFrozenHog ); const @@ -2407,6 +2410,7 @@ SDWaterOpacity:= $80; SDTint:= $80; ExplosionBorderColor:= $FF808080; + IceColor:= ($44 shl RShift) or ($97 shl GShift) or ($A9 shl BShift) or ($A0 shl AShift); WaterOpacity:= $80; cDrownSpeed.QWordValue := 257698038; // 0.06 diff -r e96bf10216ef -r 9d1d0fa8db02 share/hedgewars/Data/Graphics/Hedgehog.png Binary file share/hedgewars/Data/Graphics/Hedgehog.png has changed diff -r e96bf10216ef -r 9d1d0fa8db02 share/hedgewars/Data/Graphics/Hedgehog/amFrozenHog.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amFrozenHog.png has changed diff -r e96bf10216ef -r 9d1d0fa8db02 share/hedgewars/Data/Graphics/Hedgehog/amIceGun.png Binary file share/hedgewars/Data/Graphics/Hedgehog/amIceGun.png has changed diff -r e96bf10216ef -r 9d1d0fa8db02 share/hedgewars/Data/Graphics/icetexture.png Binary file share/hedgewars/Data/Graphics/icetexture.png has changed diff -r e96bf10216ef -r 9d1d0fa8db02 share/hedgewars/Data/Locale/ja.txt --- a/share/hedgewars/Data/Locale/ja.txt Mon Feb 25 19:48:35 2013 +0100 +++ b/share/hedgewars/Data/Locale/ja.txt Wed Feb 27 16:12:57 2013 +0100 @@ -470,62 +470,62 @@ 03:55=ユーティリティ ; Weapon Descriptions (use | as line breaks) -04:00=シンプルな手榴弾を使って敵を攻撃。そのタイマーがゼロに達するとそれが爆発する。1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド -04:01=クラスター爆弾を使用して敵を攻撃。そのタイマーがゼロに達すると、それは小さな爆弾に分割されます。1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド -04:02=風に影響されるかもしれない弾道発射体を使用して敵を攻撃。攻撃:より多くの電力を使って撮影するホールド -04:03=選択したターゲットにロックされ爆発的な蜂を起動します。その精度を向上させるためにフルパワーを使って撮影しないでください。カーソル:ピックターゲット攻撃:より多くの電力を使って撮影するホールド -04:04=2ショットでショットガンを使って敵を攻撃する。その広がりあなたのおかげで、あなたの対戦相手に危害を直接ヒットする必要はありません。攻撃:シュート(複数回) -04:05=地下に移動!地面に穴を開けると他の領域に到達するを使用しています。攻撃の開始または停止掘り -04:06=退屈?攻撃する方法はありません?あなたの弾薬を保存しますか?問題ありません!ちょうどあなたのターン、臆病者をスキップして!攻撃:戦闘せずにターンをスキップ -04:07=ロープでタイムアウトショットを使用して、巨大な距離を埋める。他の豚またはドロップ手榴弾およびそれらの他の武器にスライドするように勢いを使用しています。攻撃:ドロップ手榴弾または類似の武器:ロープロングジャンプシュートまたは解放 -04:08=狭い通路の右またはそれらの足の下鉱山をドロップすることで、離れてあなたの敵を保つ。あなた自身でそれをトリガする前に撤退してください!攻撃:あなたの足の隣に地雷を削除します。 -04:09=あなたの照準が分からない?4打差までを使用して攻撃するためにデザートイーグルを使用しています。攻撃:シュート(複数回) -04:10=ブルートフォースは常にオプションです。あなたの敵と後退の隣にあるこの古典的な爆発物をドロップします。攻撃:あなたの足の隣にあるドロップダイナマイト -04:11=マップの国境を越えてまたは水の中にそれらをバッティングして敵の豚を取り除く。またはどのようにお友達にいくつかの鉱山をノックでしょうか?攻撃:あなたの前にバットすべてを -04:12=このほとんど致命的な武道技術の力を解き放つに近いと個人的な取得します。攻撃:素晴らしいを実行します。 +04:00=シンプルな手榴弾を使って敵を攻撃。|そのタイマーがゼロに達するとそれが爆発する。|1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド +04:01=クラスター爆弾を使用して敵を攻撃。|そのタイマーがゼロに達すると、それは小さな爆弾に分割されます。|1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド +04:02=風に影響されるかもしれない弾道発射体を使用して敵を攻撃。|攻撃:より多くの電力を使って撮影するホールド +04:03=選択したターゲットにロックされ爆発的な蜂を起動します。|その精度を向上させるためにフルパワーを使って撮影しないでください。|カーソル:ピックターゲット攻撃:より多くの電力を使って撮影するホールド +04:04=2ショットでショットガンを使って敵を攻撃する。|その広がりあなたのおかげで、あなたの対戦相手に危害を直接ヒットする必要はありません。|攻撃:シュート(複数回) +04:05=地下に移動!|地面に穴を開けると他の領域に到達するを使用しています。|攻撃の開始または停止掘り +04:06=退屈?攻撃する方法はありません?あなたの弾薬を保存しますか?問題ありません!|ちょうどあなたのターン、臆病者をスキップして!|攻撃:戦闘せずにターンをスキップ +04:07=ロープでタイムアウトショットを使用して、巨大な距離を埋める。|他の豚またはドロップ手榴弾およびそれらの他の武器にスライドするように勢いを使用しています。|攻撃:ドロップ手榴弾または類似の武器:ロープロングジャンプシュートまたは解放 +04:08=狭い通路の右またはそれらの足の下鉱山をドロップすることで、離れてあなたの敵を保つ。|あなた自身でそれをトリガする前に撤退してください!|攻撃:あなたの足の隣に地雷を削除します。 +04:09=あなたの照準が分からない?4打差までを使用して攻撃するためにデザートイーグルを使用しています。|攻撃:シュート(複数回) +04:10=ブルートフォースは常にオプションです。|あなたの敵と後退の隣にあるこの古典的な爆発物をドロップします。|攻撃:あなたの足の隣にあるドロップダイナマイト +04:11=マップの国境を越えてまたは水の中にそれらをバッティングして敵の豚を取り除く。|またはどのようにお友達にいくつかの鉱山をノックでしょうか?攻撃:あなたの前にバットすべてを +04:12=このほとんど致命的な武道技術の力を解き放つに近いと個人的な取得します。|攻撃:素晴らしいを実行します。 04:13=UNUSED -04:14=高所恐怖症?優れたパラシュートをつかむ。それはあなたが遠すぎたら落ちる展開と秋のダメージを受けてから豚を保存します。攻撃:ドロップ手榴弾または類似の武器:パラシュートロングジャンプを伸ばし -04:15=爆撃の実行を使用して敵を攻撃する飛行機の中で呼び出します。左右:選択してターゲット領域:攻撃方向のカーソルを決定 -04:16=ターゲットエリアにいくつかの鉱山をドロップするには飛行機の中で呼び出します。左右:選択してターゲット領域:攻撃方向のカーソルを決定 -04:17=避難が必要ですか?あなたがカバー付与固体地面にトンネルを掘るためにブロートーチを使用しています。攻撃の開始または停止掘り -04:18=追加の保護が必要な場合、または地面を通過したいですか?好きなように、いくつかの桁に置きます。有効な位置に配置桁:左右:カーソルを配置する選択桁 -04:19=それはあなたが数秒以内に危険な状況から豚を保存することができますように、右瞬間テレポーテーションで使用するほぼすべての武器をより強力にすることができます。カーソル:選択してターゲット領域 -04:20=別の豚と、現在のターンを再生することができます。攻撃:スイッチング豚を有効にする -04:21=インパクト時に複数の爆弾を解放します手榴弾のような弾丸を撃つ。攻撃:フルパワーで撃つ -04:22=だけでなく、インディジョーンズのために!鞭は多くの状況で有用な武器である。あなたが崖から誰かを突き出すしたい場合は特に。攻撃:あなたの前にストライクのすべて -04:23=あなたが失うものは何もない場合、これはかなり便利かもしれません。彼の方法上のすべてを傷つけると終了時に爆発し、特定の方向に彼を起動することで、豚を生け贄に捧げる。攻撃:壊滅的な、致命的な攻撃を開始 -04:24=誕生日おめでとう!このケーキを起動し、それが右の敵の隣に歩いて、彼らが爆発的パーティを持たせてみましょう。ケーキは、ほぼすべての地形を通過することができますが、彼は以前、この方法を爆発させるかもしれません。攻撃:ケーキを起動するか、停止させると爆発する -04:25=(そして、いくつかのギャップや穴)が豚に向かってジャンプすることがあなたの敵を取得するには、この変装キットを使用しています。攻撃:キットを使用して、別の豚を誘惑しよう -04:26=あなたの敵で、このジューシーなスイカをスローします。タイマーの期限が切れると、それはいくつかの爆発的な断片に分割されます。1-5:セットスイカのタイマー攻撃:より多くの電力を使って撮影するホールド -04:27=この悪魔のよう爆発を使用して、あなたの対戦相手に業火の雨してみましょう。近すぎる小さな火災が長く続くかもしれないと爆発に得ることはありません。攻撃:より多くの電力を使って撮影するホールド -04:28=このロケットを打ち上げた後の短い時間、それは固体地面を掘削を開始し、そのヒューズがトリガされると爆発するか、再び再浮上します。攻撃:より多くの電力を使って撮影するホールド -04:29=これは小さな子供のためのものではありません!ボール銃は爆薬を充填した小さな色のボールのトンを発生させます。攻撃:アップダウン、フルパワーでシュートを目指して進みます -04:30=強力なナパームストライキを起動するには飛行機の中で呼び出します。適切にこの攻撃を目指してそこに座って不運な豚を含む風景の巨大な部分を根絶することができます。左右:選択してターゲット領域:攻撃方向のカーソルを決定 -04:31=RCプレーンは箱を収集したり、遠く離れた豚を攻撃するのに理想的な武器です。どちらの敵にそれを操縦するか、最初のいくつかの爆弾をドロップします。攻撃:ワルキューレが戦闘に乗りましょう左右:平面ステアジャンプ平面またはドロップロング爆弾を起動します。 -04:32=低重力はどんなダイエットよりも効果的です!高く、長い距離を飛び越えたり、敵がさらに飛ぶしましょう。攻撃:アクティブ -04:33=時には、いくつかのより多くのダメージを与えるためにその少し余分なブーストをちょうど必要があります。攻撃:アクティブ -04:34=私に触れることができない!攻撃:アクティブ -04:35=時には時間が早すぎる実行している。あなたの攻撃を完了するために、いくつかの余分な秒をつかむ。攻撃:アクティブ -04:36=さて、時にはあなたが目指すのはあまりにも悪いです。現代の技術を使用していくつかの支援を得る。攻撃:アクティブ -04:37=日光を恐れてはいけません。それはちょうど1ターン持続しますが、あなたが他の豚に何のダメージを吸収することができるようになります。攻撃:アクティブ -04:38=スナイパーライフルは、あなたの全体の兵器庫の中で最も壊滅的な武器になります、しかし、それは接近戦で非常に効果的です。ダメージは、そのターゲットまでの距離とともに増加を与えた。攻撃:シュート(回) -04:39=空飛ぶ円盤を使用してマップの他の部分に飛ぶ。これは、マスターユーティリティのハード戦場のほぼ任意の位置に行くことができるようになりました。攻撃:最大アクティブ左右:ドロップ手榴弾または類似の武器:一方向にロングジャンプ力を適用します。 -04:40=(すぐになる)、燃焼液で満たされたこのボトルを使用して、火災のいくつかの地を設定します。攻撃:より多くの電力を使って撮影するホールド -04:41=証拠の性質も、空飛ぶ円盤を上回るかもしれません。バーディは、豚を持ち歩くとあなたの敵に卵をドロップすることができます!バーディーを使用すると、あなたのターンの時間に食べるように、迅速である!攻撃:およびドロップ卵アップ左右:一方向にフラップ -04:42=この携帯ポータル装置は、瞬時に、あなたの敵、または地形上の2点間のあなたの武器あなたを輸送することが可能です。賢明にそれを使用して、キャンペーンがあります...大成功!攻撃:サイクルポータルの色:ポータルスイッチを撃つ -04:43=あなたの音楽デビュー爆発を成功させる!天からピアノをドロップしますが、注意してください...誰かがそれを再生する必要があり、それはあなたの人生を要するかもしれない!カーソル:選択してターゲット領域F1-F9キーを押して:ピアノを弾く -04:44=これはただのチーズではなく、生物兵器だ!タイマーがゼロに達すると、それは間違いなく臭いをタッチする誰もが不幸に毒されたら、それは被害の膨大な量が発生することはありません!1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド -04:45=すべてのそれらの物理学のクラスは最終的に報われている、あなたの敵に壊滅的な正弦波を起動します。気を付けろ、この武器は非常にキックをパックします。(この武器は不完全です)攻撃力:シュート -04:46=液体炎を非常に暑いとあなたの敵をカバーしています。ほのぼの!アタックを上下にアクティブにします。左右を目指して進みます:唾の電源を変更します。 -04:47=2先端のとがった、卑劣な、粘着地雷の楽しみを倍増。連鎖反応を設定するか(あるいは両方!)攻撃を守る:より多くの電力(倍)で撮影するホールド -04:48=なぜモルすべての虐待を取得する必要があります?豚をは、単に楽しみとしてすることができます!このハンマーから良い打撃は豚の健康状態の3分の1をオフに剃るし、それらを地下に突入します。攻撃:アクティブ -04:49=あなたの友人を復活させる!しかし、これはまたあなたの敵を復活させること注意してください。攻撃:ゆっくりと復活させるために押された攻撃に注意してください。復活を加速 -04:50=誰かが地下に隠れている?ドリルのストライキでそれらを掘る!タイマーは、それを掘る方法をはるかに制御します。 -04:51=泥のボールを投げつけることによって自由なショットで取得します。刺されは、ビット、豚をバックノックする。 +04:14=高所恐怖症?優れたパラシュートをつかむ。|それはあなたが遠すぎたら落ちる展開と秋のダメージを受けてから豚を保存します。|攻撃:ドロップ手榴弾または類似の武器:パラシュートロングジャンプを伸ばし +04:15=爆撃の実行を使用して敵を攻撃する飛行機の中で呼び出します。|左右:選択してターゲット領域:攻撃方向のカーソルを決定 +04:16=ターゲットエリアにいくつかの鉱山をドロップするには飛行機の中で呼び出します。|左右:選択してターゲット領域:攻撃方向のカーソルを決定 +04:17=避難が必要ですか?あなたがカバー付与固体地面にトンネルを掘るためにブロートーチを使用しています。|攻撃の開始または停止掘り +04:18=追加の保護が必要な場合、または地面を通過したいですか?好きなように、いくつかの桁に置きます。|有効な位置に配置桁:左右:カーソルを配置する選択桁 +04:19=それはあなたが数秒以内に危険な状況から豚を保存することができますように、右瞬間テレポーテーションで使用するほぼすべての武器をより強力にすることができます。|カーソル:選択してターゲット領域 +04:20=別の豚と、現在のターンを再生することができます。|攻撃:スイッチング豚を有効にする +04:21=インパクト時に複数の爆弾を解放します手榴弾のような弾丸を撃つ。|攻撃:フルパワーで撃つ +04:22=だけでなく、インディジョーンズのために!|鞭は多くの状況で有用な武器である。|あなたが崖から誰かを突き出すしたい場合は特に。|攻撃:あなたの前にストライクのすべて +04:23=あなたが失うものは何もない場合、これはかなり便利かもしれません。|彼の方法上のすべてを傷つけると終了時に爆発し、特定の方向に彼を起動することで、豚を生け贄に捧げる。|攻撃:壊滅的な、致命的な攻撃を開始 +04:24=誕生日おめでとう!|このケーキを起動し、それが右の敵の隣に歩いて、彼らが爆発的パーティを持たせてみましょう。|ケーキは、ほぼすべての地形を通過することができますが、彼は以前、この方法を爆発させるかもしれません。|攻撃:ケーキを起動するか、停止させると爆発する +04:25=(そして、いくつかのギャップや穴)が豚に向かってジャンプすることがあなたの敵を取得するには、この変装キットを使用しています。|攻撃:キットを使用して、別の豚を誘惑しよう +04:26=あなたの敵で、このジューシーなスイカをスローします。|タイマーの期限が切れると、それはいくつかの爆発的な断片に分割されます。|1-5:セットスイカのタイマー攻撃:より多くの電力を使って撮影するホールド +04:27=この悪魔のよう爆発を使用して、あなたの対戦相手に業火の雨してみましょう。|近すぎる小さな火災が長く続くかもしれないと爆発に得ることはありません。|攻撃:より多くの電力を使って撮影するホールド +04:28=このロケットを打ち上げた後の短い時間、それは固体地面を掘削を開始し、そのヒューズがトリガされると爆発するか、再び再浮上します。|攻撃:より多くの電力を使って撮影するホールド +04:29=これは小さな子供のためのものではありません!|ボール銃は爆薬を充填した小さな色のボールのトンを発生させます。|攻撃:アップダウン、フルパワーでシュートを目指して進みます +04:30=強力なナパームストライキを起動するには飛行機の中で呼び出します。|適切にこの攻撃を目指してそこに座って不運な豚を含む風景の巨大な部分を根絶することができます。|左右:選択してターゲット領域:攻撃方向のカーソルを決定 +04:31=RCプレーンは箱を収集したり、遠く離れた豚を攻撃するのに理想的な武器です。|どちらの敵にそれを操縦するか、最初のいくつかの爆弾をドロップします。|攻撃:ワルキューレが戦闘に乗りましょう左右:平面ステアジャンプ平面またはドロップロング爆弾を起動します。 +04:32=低重力はどんなダイエットよりも効果的です!|高く、長い距離を飛び越えたり、敵がさらに飛ぶしましょう。|攻撃:アクティブ +04:33=時には、いくつかのより多くのダメージを与えるためにその少し余分なブーストをちょうど必要があります。|攻撃:アクティブ +04:34=私に触れることができない!|攻撃:アクティブ +04:35=時には時間が早すぎる実行している。|あなたの攻撃を完了するために、いくつかの余分な秒をつかむ。|攻撃:アクティブ +04:36=さて、時にはあなたが目指すのはあまりにも悪いです。|現代の技術を使用していくつかの支援を得る。|攻撃:アクティブ +04:37=日光を恐れてはいけません。|それはちょうど1ターン持続しますが、あなたが他の豚に何のダメージを吸収することができるようになります。|攻撃:アクティブ +04:38=スナイパーライフルは、あなたの全体の兵器庫の中で最も壊滅的な武器になります、しかし、それは接近戦で非常に効果的です。|ダメージは、そのターゲットまでの距離とともに増加を与えた。|攻撃:シュート(回) +04:39=空飛ぶ円盤を使用してマップの他の部分に飛ぶ。|これは、マスターユーティリティのハード戦場のほぼ任意の位置に行くことができるようになりました。|攻撃:最大アクティブ左右:ドロップ手榴弾または類似の武器:一方向にロングジャンプ力を適用します。 +04:40=(すぐになる)、燃焼液で満たされたこのボトルを使用して、火災のいくつかの地を設定します。|攻撃:より多くの電力を使って撮影するホールド +04:41=証拠の性質も、空飛ぶ円盤を上回るかもしれません。|バーディは、豚を持ち歩くとあなたの敵に卵をドロップすることができます!|バーディーを使用すると、あなたのターンの時間に食べるように、迅速である!|攻撃:およびドロップ卵アップ左右:一方向にフラップ +04:42=この携帯ポータル装置は、瞬時に、あなたの敵、または地形上の2点間のあなたの武器あなたを輸送することが可能です。|賢明にそれを使用して、キャンペーンがあります...大成功!|攻撃:サイクルポータルの色:ポータルスイッチを撃つ +04:43=あなたの音楽デビュー爆発を成功させる!|天からピアノをドロップしますが、注意してください...誰かがそれを再生する必要があり、それはあなたの人生を要するかもしれない!|カーソル:選択してターゲット領域F1-F9キーを押して:ピアノを弾く +04:44=これはただのチーズではなく、生物兵器だ!|タイマーがゼロに達すると、それは間違いなく臭いをタッチする誰もが不幸に毒されたら、それは被害の膨大な量が発生することはありません!|1-5:セットグレネードのタイマー攻撃:より多くの電力をスローするようにホールド +04:45=すべてのそれらの物理学のクラスは最終的に報われている、あなたの敵に壊滅的な正弦波を起動します。|気を付けろ、この武器は非常にキックをパックします。|(この武器は不完全です)攻撃力:シュート +04:46=液体炎を非常に暑いとあなたの敵をカバーしています。|ほのぼの!|アタックを上下にアクティブにします。|左右を目指して進みます:唾の電源を変更します。 +04:47=2先端のとがった、卑劣な、粘着地雷の楽しみを倍増。|連鎖反応を設定するか(あるいは両方!|)攻撃を守る:より多くの電力(倍)で撮影するホールド +04:48=なぜモルすべての虐待を取得する必要があります?豚をは、単に楽しみとしてすることができます!|このハンマーから良い打撃は豚の健康状態の3分の1をオフに剃るし、それらを地下に突入します。|攻撃:アクティブ +04:49=あなたの友人を復活させる!|しかし、これはまたあなたの敵を復活させること注意してください。|攻撃:ゆっくりと復活させるために押された攻撃に注意してください。|復活を加速 +04:50=誰かが地下に隠れている?ドリルのストライキでそれらを掘る!|タイマーは、それを掘る方法をはるかに制御します。 +04:51=泥のボールを投げつけることによって自由なショットで取得します。|刺されは、ビット、豚をバックノックする。 04:52=UNUSED -04:53=あなたの仲間が単独で戦うために残しながら、時間と空間を介して冒険に出る。いつでも返すように準備する、または突然死の場合、または、それらはすべて敗北しています。免責事項。あなたは一人である場合は、突然死で機能するか、キングである場合ではありません。 +04:53=あなたの仲間が単独で戦うために残しながら、時間と空間を介して冒険に出る。|いつでも返すように準備する、または突然死の場合、または、それらはすべて敗北しています。|免責事項。|あなたは一人である場合は、突然死で機能するか、キングである場合ではありません。 04:54=INCOMPLETE -04:55=スティッキーフレークのストリームをスプレー。トンネルを封鎖、敵を埋める、ブリッジを構築します。あなたが上の任意のを取得しないように注意してください! +04:55=スティッキーフレークのストリームをスプレー。|トンネルを封鎖、敵を埋める、ブリッジを構築します。|あなたが上の任意のを取得しないように注意してください! ; Game goal strings 05:00=ゲームモード