Different implementation of CreateObject() (#1214)

CreateObject() now does not reposition an object after it has been created, but rather grows it around the center of said object.
To that end a new parameter has been added to DoCon() and SetCon() and the documentation has been updated.
issue1247
Mark 2015-01-11 22:04:35 +01:00
parent a5c2e762f7
commit f9369f9eb4
9 changed files with 71 additions and 36 deletions

View File

@ -7,7 +7,7 @@
<title>DoCon</title>
<category>Objects</category>
<subcat>Status</subcat>
<version>5.1 OC</version>
<version>6.0 OC</version>
<syntax>
<rtype>void</rtype>
<params>
@ -16,7 +16,17 @@
<name>change</name>
<desc>Change of completion in percentage point (positive or negative).</desc>
</param>
</params>
<param>
<type>int</type>
<name>precision</name>
<desc>If specified, the con value will be divided by this value. No value or 0 uses the default precision of 100.</desc>
</param>
<param>
<type>bool</type>
<name>grow_from_center</name>
<desc>If specified, this parameter determines whether the object should grow from the bottommost vertex or from its center. The default value is false, which makes the object grow from the bottommost vertex.</desc>
</param>
</params>
</syntax>
<desc>Adjusts the completion value of an object. This affects the completion of construction sites or the growth of trees and living beings. If completion drops below 0, the object is removed.</desc>
<examples>
@ -36,4 +46,5 @@
</related>
</func>
<author>Sven2</author><date>2001-11</date>
<author>Marky</author><date>2015-01</date>
</funcs>

View File

@ -7,7 +7,7 @@
<title>SetCon</title>
<category>Objects</category>
<subcat>Status</subcat>
<version>5.1 OC</version>
<version>6.0 OC</version>
<syntax>
<rtype>bool</rtype>
<params>
@ -15,6 +15,16 @@
<type>int</type>
<name>con</name>
<desc>Completion/growth in percent</desc>
</param>
<param>
<type>int</type>
<name>precision</name>
<desc>If specified, the con value will be divided by this value. No value or 0 uses the default precision of 100.</desc>
</param>
<param>
<type>bool</type>
<name>grow_from_center</name>
<desc>If specified, this parameter determines whether the object should grow from the bottommost vertex or from its center. The default value is false, which makes the object grow from the bottommost vertex.</desc>
</param>
</params>
</syntax>
@ -34,4 +44,5 @@
</func>
<author>flgr</author><date>2002-01</date>
<author>matthes</author><date>2004-07</date>
<author>Marky</author><date>2015-01</date>
</funcs>

View File

@ -33,9 +33,9 @@ global func SetVelocity(int angle, int speed, int precAng, int precSpd)
}
// Sets the completion of this to new_con.
global func SetCon(int new_con)
global func SetCon(int new_con, int precision, bool grow_from_center)
{
return DoCon(new_con - GetCon());
return DoCon(new_con - GetCon(), precision, grow_from_center);
}
global func GetObjAlpha()

View File

@ -1000,7 +1000,7 @@ C4Object* C4Game::NewObject( C4PropList *pDef, C4Object *pCreator,
int32_t iOwner, C4ObjectInfo *pInfo,
int32_t iX, int32_t iY, int32_t iR,
C4Real xdir, C4Real ydir, C4Real rdir,
int32_t iCon, int32_t iController)
int32_t iCon, int32_t iController, bool grow_from_center)
{
// Safety
if (!pDef) return NULL;
@ -1026,8 +1026,8 @@ C4Object* C4Game::NewObject( C4PropList *pDef, C4Object *pCreator,
pObj->Call(PSF_Construction, &pars);
// AssignRemoval called? (Con 0)
if (!pObj->Status) { return NULL; }
// Do initial con
pObj->DoCon(iCon);
// Do initial con (grow)
pObj->DoCon(iCon, grow_from_center);
// AssignRemoval called? (Con 0)
if (!pObj->Status) { return NULL; }
// Success
@ -1043,7 +1043,7 @@ void C4Game::DeleteObjects(bool fDeleteInactive)
}
C4Object* C4Game::CreateObject(C4ID id, C4Object *pCreator, int32_t iOwner,
int32_t x, int32_t y, int32_t r,
int32_t x, int32_t y, int32_t r, bool grow_from_center,
C4Real xdir, C4Real ydir, C4Real rdir, int32_t iController)
{
C4Def *pDef;
@ -1054,12 +1054,12 @@ C4Object* C4Game::CreateObject(C4ID id, C4Object *pCreator, int32_t iOwner,
iOwner,NULL,
x,y,r,
xdir,ydir,rdir,
FullCon, iController);
FullCon, iController, grow_from_center);
}
C4Object* C4Game::CreateObject(C4PropList * PropList, C4Object *pCreator, int32_t iOwner,
int32_t x, int32_t y, int32_t r,
C4Real xdir, C4Real ydir, C4Real rdir, int32_t iController)
int32_t x, int32_t y, int32_t r, bool grow_from_center,
C4Real xdir, C4Real ydir, C4Real rdir, int32_t iController)
{
// check Definition
if (!PropList || !PropList->GetDef()) return NULL;
@ -1068,7 +1068,7 @@ C4Object* C4Game::CreateObject(C4PropList * PropList, C4Object *pCreator, int32_
iOwner,NULL,
x,y,r,
xdir,ydir,rdir,
FullCon, iController);
FullCon, iController, grow_from_center);
}
C4Object* C4Game::CreateInfoObject(C4ObjectInfo *cinf, int32_t iOwner,
@ -1084,7 +1084,7 @@ C4Object* C4Game::CreateInfoObject(C4ObjectInfo *cinf, int32_t iOwner,
iOwner,cinf,
tx,ty,0,
Fix0,Fix0,Fix0,
FullCon, NO_OWNER );
FullCon, NO_OWNER, false);
}
C4Object* C4Game::CreateObjectConstruction(C4PropList * PropList,
@ -1121,7 +1121,7 @@ C4Object* C4Game::CreateObjectConstruction(C4PropList * PropList,
iOwner,NULL,
iX,iBY,0,
Fix0,Fix0,Fix0,
iCon, pCreator ? pCreator->Controller : NO_OWNER))) return NULL;
iCon, pCreator ? pCreator->Controller : NO_OWNER, false))) return NULL;
return pObj;
}
@ -1413,6 +1413,7 @@ void C4Game::CastObjects(C4ID id, C4Object *pCreator, int32_t num, int32_t level
C4Real rdir = itofix(Random(3)+1);
C4Object *obj = CreateObject(id,pCreator,iOwner,
tx,ty,angle,
false,
xdir,
ydir,
rdir, iController);

View File

@ -178,10 +178,10 @@ public:
// Object functions
void ClearPointers(C4Object *cobj);
C4Object *CreateObject(C4PropList * type, C4Object *pCreator, int32_t owner=NO_OWNER,
int32_t x=50, int32_t y=50, int32_t r=0,
int32_t x=50, int32_t y=50, int32_t r=0, bool grow_from_center=false,
C4Real xdir=Fix0, C4Real ydir=Fix0, C4Real rdir=Fix0, int32_t iController=NO_OWNER);
C4Object *CreateObject(C4ID type, C4Object *pCreator, int32_t owner=NO_OWNER,
int32_t x=50, int32_t y=50, int32_t r=0,
int32_t x=50, int32_t y=50, int32_t r=0, bool grow_from_center=false,
C4Real xdir=Fix0, C4Real ydir=Fix0, C4Real rdir=Fix0, int32_t iController=NO_OWNER);
C4Object *CreateObjectConstruction(C4PropList * type,
C4Object *pCreator,
@ -276,7 +276,7 @@ protected:
int32_t owner, C4ObjectInfo *info,
int32_t tx, int32_t ty, int32_t tr,
C4Real xdir, C4Real ydir, C4Real rdir,
int32_t con, int32_t iController);
int32_t con, int32_t iController, bool grow_from_center);
void ClearObjectPtrs(C4Object *tptr);
void ObjectRemovalCheck();

View File

@ -124,8 +124,8 @@ static C4Object *FnCreateObjectAbove(C4PropList * _this,
{
if (Object(_this)) // Local object calls override
{
iXOffset+=Object(_this)->GetX();
iYOffset+=Object(_this)->GetY();
iXOffset += Object(_this)->GetX();
iYOffset += Object(_this)->GetY();
}
long iOwner = owner;
@ -137,7 +137,7 @@ static C4Object *FnCreateObjectAbove(C4PropList * _this,
iOwner = NO_OWNER;
}
C4Object *pNewObj = Game.CreateObject(PropList,Object(_this),iOwner,iXOffset,iYOffset);
C4Object *pNewObj = Game.CreateObject(PropList, Object(_this), iOwner, iXOffset, iYOffset);
// Set initial controller to creating controller, so more complicated cause-effect-chains can be traced back to the causing player
if (pNewObj && Object(_this) && Object(_this)->Controller > NO_OWNER) pNewObj->Controller = Object(_this)->Controller;
@ -148,21 +148,30 @@ static C4Object *FnCreateObjectAbove(C4PropList * _this,
static C4Object *FnCreateObject(C4PropList * _this,
C4PropList * PropList, long iXOffset, long iYOffset, Nillable<long> owner)
{
C4Object *pNewObj = FnCreateObjectAbove(_this, PropList, iXOffset, iYOffset, owner);
if (Object(_this)) // Local object calls override
{
iXOffset += Object(_this)->GetX();
iYOffset += Object(_this)->GetY();
}
// would have called FnSetPosition(), but maybe including that header is not desired here
// maybe a totally different approach would be even better? Think of a parameter in C4Game::CreateObject?
// the problem here is, that the object may flatten the landscape and then get teleported somewhere else
// this is usually just a few pixels, but it is still not desirable
long iPrec = 1;
C4Real i_x = itofix(iXOffset, iPrec), i_y = itofix(iYOffset, iPrec);
pNewObj->ForcePosition(i_x, i_y);
// update liquid
pNewObj->UpdateInLiquid();
long iOwner = owner;
if (owner.IsNil())
{
if (Object(_this))
iOwner = Object(_this)->Controller;
else
iOwner = NO_OWNER;
}
C4Object *pNewObj = Game.CreateObject(PropList, Object(_this), iOwner, iXOffset, iYOffset, 0, true);
// Set initial controller to creating controller, so more complicated cause-effect-chains can be traced back to the causing player
if (pNewObj && Object(_this) && Object(_this)->Controller > NO_OWNER) pNewObj->Controller = Object(_this)->Controller;
return pNewObj;
}
static C4Object *FnCreateConstruction(C4PropList * _this,
C4PropList * PropList, long iXOffset, long iYOffset, Nillable<long> owner,
long iCompletion, bool fTerrain, bool fCheckSite)

View File

@ -1250,7 +1250,7 @@ void C4Object::DoBreath(int32_t iChange)
Call(PSF_BreathChange,&C4AulParSet(C4VInt(iChange)));
}
void C4Object::DoCon(int32_t iChange)
void C4Object::DoCon(int32_t iChange, bool grow_from_center)
{
C4Real strgt_con_b = fix_y + Shape.GetBottom();
bool fWasFull = (Con>=FullCon);
@ -1270,7 +1270,10 @@ void C4Object::DoCon(int32_t iChange)
// shape and position
UpdateShape();
// make the bottom-most vertex stay in place
fix_y = strgt_con_b - Shape.GetBottom();
if (!grow_from_center)
{
fix_y = strgt_con_b - Shape.GetBottom();
}
// Face (except for the shape)
UpdateFace(false);

View File

@ -293,7 +293,7 @@ public:
void DoEnergy(int32_t iChange, bool fExact, int32_t iCause, int32_t iCausedByPlr);
void UpdatLastEnergyLossCause(int32_t iNewCausePlr);
void DoBreath(int32_t iChange);
void DoCon(int32_t iChange);
void DoCon(int32_t iChange, bool grow_from_center);
int32_t GetCon() const { return Con; }
void DoExperience(int32_t change);
bool Promote(int32_t torank, bool exception, bool fForceRankName);

View File

@ -155,10 +155,10 @@ static C4Void FnSetPosition(C4Object *Obj, long iX, long iY, bool fCheckBounds,
return C4Void();
}
static C4Void FnDoCon(C4Object *Obj, long iChange, long iPrec)
static C4Void FnDoCon(C4Object *Obj, long iChange, long iPrec, bool bGrowFromCenter)
{
if (!iPrec) iPrec = 100;
Obj->DoCon(FullCon*iChange/iPrec);
Obj->DoCon(FullCon*iChange / iPrec, bGrowFromCenter);
return C4Void();
}