forked from Mirrors/openclonk
277 lines
7.6 KiB
C++
277 lines
7.6 KiB
C++
/*
|
|
* OpenClonk, http://www.openclonk.org
|
|
*
|
|
* Copyright (c) 1998-2000 Matthes Bender
|
|
* Copyright (c) 2002, 2005-2006 Sven Eberhardt
|
|
* Copyright (c) 2005 Peter Wortmann
|
|
* Copyright (c) 2005-2008 Günther Brammer
|
|
* Copyright (c) 2009 Nicolas Hake
|
|
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
*
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
* to OpenClonk.
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
* See isc_license.txt for full license and disclaimer.
|
|
*
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
* See clonk_trademark_license.txt for full license.
|
|
*/
|
|
|
|
/* Small member of the landscape class to handle the sky background */
|
|
|
|
#include <C4Include.h>
|
|
#include <C4Sky.h>
|
|
|
|
#ifndef BIG_C4INCLUDE
|
|
#include <C4Game.h>
|
|
#include <C4Random.h>
|
|
#include <C4SurfaceFile.h>
|
|
#include <C4Components.h>
|
|
#include <C4Wrappers.h>
|
|
#endif
|
|
|
|
static BOOL SurfaceEnsureSize(C4Surface **ppSfc, int iMinWdt, int iMinHgt)
|
|
{
|
|
// safety
|
|
if (!ppSfc) return FALSE; if (!*ppSfc) return FALSE;
|
|
// get size
|
|
int iWdt=(*ppSfc)->Wdt, iHgt=(*ppSfc)->Hgt;
|
|
int iDstWdt=iWdt, iDstHgt=iHgt;
|
|
// check if it must be enlarged
|
|
while (iDstWdt<iMinWdt) iDstWdt+=iWdt;
|
|
while (iDstHgt<iMinHgt) iDstHgt+=iHgt;
|
|
// Without shaders, the textures need to be small for the FoW.
|
|
if (iDstWdt==iWdt && iDstHgt==iHgt && lpDDraw->IsShaderific()) return TRUE;
|
|
// create new surface
|
|
C4Surface *pNewSfc=new C4Surface();
|
|
if (!pNewSfc->Create(iDstWdt, iDstHgt, false, false, lpDDraw->IsShaderific() ? 0 : 64))
|
|
{
|
|
delete pNewSfc;
|
|
return FALSE;
|
|
}
|
|
// blit tiled into dest surface
|
|
lpDDraw->BlitSurfaceTile2(*ppSfc, pNewSfc, 0, 0, iDstWdt, iDstHgt, 0, 0, FALSE);
|
|
// destroy old surface, assign new
|
|
delete *ppSfc; *ppSfc=pNewSfc;
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
void C4Sky::SetFadePalette(int32_t *ipColors)
|
|
{
|
|
// If colors all zero, use game palette default blue
|
|
if (ipColors[0]+ipColors[1]+ipColors[2]+ipColors[3]+ipColors[4]+ipColors[5]==0)
|
|
{
|
|
BYTE *pClr=::GraphicsResource.GamePalette+3*CSkyDef1;
|
|
FadeClr1=C4RGB(pClr[0], pClr[1], pClr[2]);
|
|
FadeClr2=C4RGB(pClr[3*19+0], pClr[3*19+1], pClr[3*19+2]);
|
|
}
|
|
else
|
|
{
|
|
// set colors
|
|
FadeClr1=C4RGB(ipColors[0], ipColors[1], ipColors[2]);
|
|
FadeClr2=C4RGB(ipColors[3], ipColors[4], ipColors[5]);
|
|
}
|
|
}
|
|
|
|
BOOL C4Sky::Init(bool fSavegame)
|
|
{
|
|
int32_t skylistn;
|
|
|
|
// reset scrolling pos+speed
|
|
// not in savegame, because it will have been loaded from game data there
|
|
if (!fSavegame)
|
|
{
|
|
x=y=xdir=ydir=0; ParX=ParY=10; ParallaxMode=0;
|
|
}
|
|
|
|
// Check for sky bitmap in scenario file
|
|
Surface = new C4Surface();
|
|
bool loaded = !!Surface->LoadAny(Game.ScenarioFile,C4CFN_Sky,true,true);
|
|
|
|
// Else, evaluate scenario core landscape sky default list
|
|
if (!loaded)
|
|
{
|
|
// Scan list sections
|
|
SReplaceChar(Game.C4S.Landscape.SkyDef,',',';'); // modifying the C4S here...!
|
|
skylistn=SCharCount(';',Game.C4S.Landscape.SkyDef)+1;
|
|
char str[402];
|
|
SCopySegment(Game.C4S.Landscape.SkyDef,SeededRandom(Game.RandomSeed,skylistn),str,';');
|
|
SClearFrontBack(str);
|
|
// Sky tile specified, try load
|
|
if (*str && !SEqual(str,"Default"))
|
|
{
|
|
// Check for sky tile in scenario file
|
|
loaded = !!Surface->LoadAny(Game.ScenarioFile,str,true,true);
|
|
if (!loaded)
|
|
{
|
|
loaded = !!Surface->LoadAny(::GraphicsResource.Files, str, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (loaded)
|
|
{
|
|
// surface loaded, store first color index
|
|
/*if (Surface->HasOwnPal())
|
|
{
|
|
FadeClr1=Surface->pPal->GetClr(0);
|
|
FadeClr2=Surface->pPal->GetClr(19);
|
|
}
|
|
else*/
|
|
FadeClr1=FadeClr2=0xffffff;
|
|
// enlarge surface to avoid slow 1*1-px-skies
|
|
if (!SurfaceEnsureSize(&Surface, 128, 128)) return FALSE;
|
|
|
|
// set parallax scroll mode
|
|
switch (Game.C4S.Landscape.SkyScrollMode)
|
|
{
|
|
case 0: // default: no scrolling
|
|
break;
|
|
case 1: // go with the wind in xdir, and do some parallax scrolling in ydir
|
|
ParallaxMode=C4SkyPM_Wind;
|
|
ParY=20;
|
|
break;
|
|
case 2: // parallax in both directions
|
|
ParX=ParY=20;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// Else, try creating default Surface
|
|
if (!loaded)
|
|
{
|
|
SetFadePalette(Game.C4S.Landscape.SkyDefFade);
|
|
delete Surface;
|
|
Surface = 0;
|
|
}
|
|
|
|
// no sky - using fade in newgfx
|
|
if (!Surface)
|
|
return TRUE;
|
|
|
|
// Store size
|
|
if (Surface)
|
|
{
|
|
int iWdt,iHgt;
|
|
if (Surface->GetSurfaceSize(iWdt, iHgt))
|
|
{
|
|
Width = iWdt; Height = iHgt;
|
|
}
|
|
}
|
|
|
|
// Success
|
|
return TRUE;
|
|
}
|
|
|
|
void C4Sky::Default()
|
|
{
|
|
Width=Height=0;
|
|
Surface=NULL;
|
|
x=y=xdir=ydir=0;
|
|
Modulation=0x00ffffff;
|
|
ParX=ParY=10;
|
|
ParallaxMode=C4SkyPM_Fixed;
|
|
BackClr=0;
|
|
BackClrEnabled=FALSE;
|
|
}
|
|
|
|
C4Sky::~C4Sky()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void C4Sky::Clear()
|
|
{
|
|
delete Surface; Surface=NULL;
|
|
Modulation=0x00ffffff;
|
|
}
|
|
|
|
BOOL C4Sky::Save(C4Group &hGroup)
|
|
{
|
|
// Sky-saving disabled by scenario core
|
|
// (With this option enabled, script-defined changes to sky palette will not be saved!)
|
|
if (Game.C4S.Landscape.NoSky)
|
|
{
|
|
hGroup.Delete(C4CFN_Sky);
|
|
return TRUE;
|
|
}
|
|
// no sky?
|
|
if (!Surface) return TRUE;
|
|
// FIXME?
|
|
// Success
|
|
return TRUE;
|
|
}
|
|
|
|
void C4Sky::Execute()
|
|
{
|
|
// surface exists?
|
|
if (!Surface) return;
|
|
// advance pos
|
|
x+=xdir; y+=ydir;
|
|
// clip by bounds
|
|
if (x>=itofix(Width)) x-=itofix(Width);
|
|
if (y>=itofix(Height)) y-=itofix(Height);
|
|
// update speed
|
|
if (ParallaxMode == C4SkyPM_Wind) xdir=FIXED100(Game.Weather.Wind);
|
|
}
|
|
|
|
void C4Sky::Draw(C4TargetFacet &cgo)
|
|
{
|
|
// background color?
|
|
if (BackClrEnabled) Application.DDraw->DrawBoxDw(cgo.Surface, cgo.X, cgo.Y, cgo.X+cgo.Wdt, cgo.Y+cgo.Hgt, BackClr);
|
|
// sky surface?
|
|
if (Modulation != 0xffffff) Application.DDraw->ActivateBlitModulation(Modulation);
|
|
if (Surface)
|
|
{
|
|
// blit parallax sky
|
|
int iParX = cgo.TargetX * 10 / ParX - fixtoi(x);
|
|
int iParY = cgo.TargetY * 10 / ParY - fixtoi(y);
|
|
Application.DDraw->BlitSurfaceTile2(Surface, cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt, iParX, iParY, FALSE);
|
|
}
|
|
else
|
|
{
|
|
// no sky surface: blit sky fade
|
|
DWORD dwClr1=GetSkyFadeClr(cgo.TargetY);
|
|
DWORD dwClr2=GetSkyFadeClr(cgo.TargetY+cgo.Hgt);
|
|
Application.DDraw->DrawBoxFade(cgo.Surface, cgo.X, cgo.Y, cgo.Wdt, cgo.Hgt, dwClr1, dwClr1, dwClr2, dwClr2, cgo.TargetX, cgo.TargetY);
|
|
}
|
|
if (Modulation != 0xffffff) Application.DDraw->DeactivateBlitModulation();
|
|
// done
|
|
}
|
|
|
|
DWORD C4Sky::GetSkyFadeClr(int32_t iY)
|
|
{
|
|
int32_t iPos2=(iY*256)/GBackHgt; int32_t iPos1=256-iPos2;
|
|
return (((((FadeClr1&0xff00ff)*iPos1 + (FadeClr2&0xff00ff)*iPos2) & 0xff00ff00)
|
|
| (((FadeClr1&0x00ff00)*iPos1 + (FadeClr2&0x00ff00)*iPos2) & 0x00ff0000))>>8)
|
|
| (FadeClr1 & 0xff000000);
|
|
}
|
|
|
|
bool C4Sky::SetModulation(DWORD dwWithClr, DWORD dwBackClr)
|
|
{
|
|
Modulation=dwWithClr;
|
|
BackClr=dwBackClr;
|
|
BackClrEnabled=(Modulation>>24) ? TRUE : FALSE;
|
|
return true;
|
|
}
|
|
|
|
void C4Sky::CompileFunc(StdCompiler *pComp)
|
|
{
|
|
pComp->Value(mkNamingAdapt(mkCastIntAdapt(x), "X", Fix0));
|
|
pComp->Value(mkNamingAdapt(mkCastIntAdapt(y), "Y", Fix0));
|
|
pComp->Value(mkNamingAdapt(mkCastIntAdapt(xdir),"XDir", Fix0));
|
|
pComp->Value(mkNamingAdapt(mkCastIntAdapt(ydir),"YDir", Fix0));
|
|
pComp->Value(mkNamingAdapt(Modulation, "Modulation", 0x00ffffffU));
|
|
pComp->Value(mkNamingAdapt(ParX, "ParX", 10));
|
|
pComp->Value(mkNamingAdapt(ParY, "ParY", 10));
|
|
pComp->Value(mkNamingAdapt(ParallaxMode, "ParMode", C4SkyPM_Fixed));
|
|
pComp->Value(mkNamingAdapt(BackClr, "BackClr", 0));
|
|
pComp->Value(mkNamingAdapt(BackClrEnabled, "BackClrEnabled", false));
|
|
}
|