2012-04-03 00:55:55 +00:00
/*--
Objects . c
2015-06-08 19:06:18 +00:00
Authors : Maikel , boni , Ringwaul , Sven2 , flgr , Clonkonaut , G ü nther , Randrian
2012-04-03 00:55:55 +00:00
Functions generally applicable to objects ; not enough to be worth distinct scripts though .
- - */
// Does not set the speed of an object. But you can set two components of the velocity vector with this function.
global func SetSpeed ( int x_dir , int y_dir , int prec )
{
SetXDir ( x_dir , prec ) ;
SetYDir ( y_dir , prec ) ;
return ;
}
// Sets an objects's speed and its direction, doesn't it?
// Can set either speed or angle of velocity, or both
global func SetVelocity ( int angle , int speed , int precAng , int precSpd )
{
2012-08-10 00:37:53 +00:00
if ( ! precSpd ) precSpd = 10 ;
if ( ! precAng ) precAng = 1 ;
2012-04-03 00:55:55 +00:00
if ( ! speed )
speed = Distance ( 0 , 0 , GetXDir ( precSpd ) , GetYDir ( precSpd ) ) ;
if ( ! angle )
angle = Angle ( 0 , 0 , GetXDir ( precSpd ) , GetYDir ( precSpd ) , precAng ) ;
2012-08-10 00:37:53 +00:00
2012-04-03 00:55:55 +00:00
var x_dir = Sin ( angle , speed , precAng ) ;
var y_dir = - Cos ( angle , speed , precAng ) ;
SetXDir ( x_dir , precSpd ) ;
SetYDir ( y_dir , precSpd ) ;
return ;
}
// Sets the completion of this to new_con.
2015-01-11 21:04:35 +00:00
global func SetCon ( int new_con , int precision , bool grow_from_center )
2012-04-03 00:55:55 +00:00
{
2015-01-11 21:04:35 +00:00
return DoCon ( new_con - GetCon ( ) , precision , grow_from_center ) ;
2012-04-03 00:55:55 +00:00
}
2012-11-11 20:43:20 +00:00
global func GetObjAlpha ( )
{
return ( GetClrModulation ( ) > > 24 ) & 0xFF ;
}
2012-04-03 00:55:55 +00:00
// Sets the object's transparency.
global func SetObjAlpha ( int by_alpha )
{
var clr_mod = GetClrModulation ( ) ;
if ( ! clr_mod )
clr_mod = by_alpha < < 24 ;
else
clr_mod = clr_mod & 16777215 | by_alpha < < 24 ;
return SetClrModulation ( clr_mod ) ;
}
2015-09-15 02:25:27 +00:00
global func MakeInvincible ( bool allow_fire )
2012-04-03 00:55:55 +00:00
{
2015-09-15 02:25:27 +00:00
if ( ! this ) return false ;
var fx = GetEffect ( " IntInvincible " , this ) ;
if ( ! fx ) fx = AddEffect ( " IntInvincible " , this , 300 , 0 ) ;
if ( ! fx ) return false ;
fx . allow_fire = allow_fire ;
if ( ! allow_fire & & this - > OnFire ( ) ) this - > Extinguish ( ) ;
return true ;
2012-04-03 00:55:55 +00:00
}
2015-09-15 02:25:27 +00:00
global func FxIntInvincibleDamage ( target )
2014-07-05 13:25:30 +00:00
{
2015-09-15 02:25:27 +00:00
// avert all damage
return 0 ;
2014-07-05 13:25:30 +00:00
}
2015-09-15 02:25:27 +00:00
global func FxIntInvincibleEffect ( string new_name , object target , proplist fx )
2012-04-03 00:55:55 +00:00
{
2015-09-15 02:25:27 +00:00
// Block fire effects.
if ( WildcardMatch ( new_name , " *Fire* " ) & & ! fx . allow_fire )
return FX_Effect_Deny ;
// All other effects are okay.
return FX_OK ;
}
global func FxIntInvincibleSaveScen ( object obj , proplist fx , proplist props )
{
// this is invincible. Save to scenario.
2015-09-17 03:30:23 +00:00
props - > AddCall ( " Invincible " , obj , " MakeInvincible " , fx . allow_fire ) ;
2015-09-15 02:25:27 +00:00
return true ;
}
// Removes invincibility from object
global func ClearInvincible ( )
{
if ( ! this ) return nil ;
return RemoveEffect ( " IntInvincible " , this ) ;
2012-04-03 00:55:55 +00:00
}
// Move an object by the given parameters relative to its position.
global func MovePosition ( int x , int y , int prec )
{
SetPosition ( GetX ( prec ) + x , GetY ( prec ) + y , nil , prec ) ;
}
2012-04-15 14:14:29 +00:00
// Returns the position as an array
2012-05-06 16:10:36 +00:00
global func GetPosition ( int prec )
2012-04-15 14:14:29 +00:00
{
return [ GetX ( prec ) , GetY ( prec ) ] ;
}
2012-04-03 00:55:55 +00:00
// Speed the calling object into the given direction (angle)
2012-08-10 00:37:53 +00:00
global func LaunchProjectile ( int angle , int dist , int speed , int x , int y , int precAng , int precSpd , bool rel_x )
2012-04-03 00:55:55 +00:00
{
// dist: Distance object travels on angle. Offset from calling object.
// x: X offset from container's center
// y: Y offset from container's center
// rel_x: if true, makes the X offset relative to container direction. (x=+30 will become x=-30 when Clonk turns left. This way offset always stays in front of a Clonk.)
2013-05-24 18:45:32 +00:00
var x_offset = x ? ? Sin ( angle , dist , precAng ) ;
var y_offset = y ? ? - Cos ( angle , dist , precAng ) ;
2012-08-10 00:37:53 +00:00
if ( ! precAng ) precAng = 1 ;
if ( ! precSpd ) precSpd = 10 ;
2012-04-03 00:55:55 +00:00
if ( Contained ( ) ! = nil & & rel_x = = true )
if ( Contained ( ) - > GetDir ( ) = = 0 )
x = - x ;
if ( Contained ( ) ! = nil )
{
2013-05-24 18:45:32 +00:00
Exit ( x_offset , y_offset , angle / precAng ) ;
2012-08-10 00:37:53 +00:00
SetVelocity ( angle , speed , precAng , precSpd ) ;
2012-04-03 00:55:55 +00:00
return true ;
}
if ( Contained ( ) = = nil )
{
2013-05-24 18:45:32 +00:00
SetPosition ( GetX ( ) + x_offset , GetY ( ) + y_offset ) ;
2012-08-10 00:37:53 +00:00
SetR ( angle / precAng ) ;
SetVelocity ( angle , speed , precAng , precSpd ) ;
2012-04-03 00:55:55 +00:00
return true ;
}
return false ;
}
// Sets the MaxEnergy value of an object and does the necessary callbacks.
global func SetMaxEnergy ( int value )
{
if ( ! this )
return ;
value * = 1000 ;
var old_maxenergy = this . MaxEnergy ;
this . MaxEnergy = value ;
// Change current energy percentage wise and implicit callback.
DoEnergy ( GetEnergy ( ) * ( value - old_maxenergy ) / old_maxenergy ) ;
return ;
}
// Returns the MaxEnergy value of an object.
global func GetMaxEnergy ( )
{
if ( ! this )
return ;
return this . MaxEnergy / 1000 ;
}
// Sets the MaxBreath value of an object and does the necessary callbacks.
global func SetMaxBreath ( int value )
{
if ( ! this )
return ;
var old_maxbreath = this . MaxBreath ;
this . MaxBreath = value ;
// Change current breath percentage wise and implicit callback.
DoBreath ( GetBreath ( ) * ( value - old_maxbreath ) / old_maxbreath ) ;
return ;
}
// Returns the MaxBreath value of an object.
global func GetMaxBreath ( )
{
if ( ! this )
return ;
return this . MaxBreath ;
}
// Makes an object gain Con until it is FullCon
2012-06-05 20:51:09 +00:00
global func StartGrowth ( int value /* the value the object grows approx. every second, in tenths of percent */ )
2012-04-03 00:55:55 +00:00
{
2012-04-17 12:06:40 +00:00
var effect ;
2015-08-28 03:28:41 +00:00
effect = AddEffect ( " IntGrowth " , this , 1 , 35 , this , nil , value ) ;
2012-04-17 12:06:40 +00:00
effect . Time = Random ( 35 ) ;
return effect ;
2012-04-03 00:55:55 +00:00
}
global func StopGrowth ( )
{
return RemoveEffect ( " IntGrowth " , this ) ;
}
global func GetGrowthValue ( )
{
var e = GetEffect ( " IntGrowth " , this ) ;
if ( ! e ) return 0 ;
return e . growth ;
}
global func FxIntGrowthStart ( object obj , effect , int temporary , int value )
{
if ( ! temporary ) effect . growth = value ;
}
global func FxIntGrowthTimer ( object obj , effect )
{
if ( obj - > OnFire ( ) ) return ;
obj - > DoCon ( effect . growth , 1000 ) ;
2015-09-17 21:55:48 +00:00
if ( ! obj ) return FX_Execute_Kill ; // Negative growth might have removed the object
2012-04-03 00:55:55 +00:00
var done = obj - > GetCon ( 1000 ) > = 1000 ;
return - done ;
}
// Plays hit sounds for an average object made of stone or stone-like material.
// x and y need to be the parameters passed to Hit() from the engine.
global func StonyObjectHit ( int x , int y )
{
// Failsafe
if ( ! this ) return false ;
var xdir = GetXDir ( ) , ydir = GetYDir ( ) ;
if ( x ) x = x / Abs ( x ) ;
if ( y ) y = y / Abs ( y ) ;
// Check for solid in hit direction
var i = 0 ;
var average_obj_size = Distance ( 0 , 0 , GetObjWidth ( ) , GetObjHeight ( ) ) / 2 + 2 ;
while ( ! GBackSolid ( x * i , y * i ) & & i < average_obj_size ) i + + ;
// To catch some high speed cases: if no solid found, check directly beneath
if ( ! GBackSolid ( x * i , y * i ) )
while ( ! GBackSolid ( x * i , y * i ) & & i < average_obj_size ) i + + ;
// Check if digfree
if ( ! GetMaterialVal ( " DigFree " , " Material " , GetMaterial ( x * i , y * i ) ) & & GBackSolid ( x * i , y * i ) )
2015-12-13 21:14:55 +00:00
return Sound ( " Hits::Materials::Rock::RockHit? " ) ;
2012-04-03 00:55:55 +00:00
// Else play standard sound
if ( Distance ( 0 , 0 , xdir , ydir ) > 10 )
2015-12-13 21:14:55 +00:00
return Sound ( " Hits::SoftTouch? " ) ;
2012-04-03 00:55:55 +00:00
else
2015-12-13 21:14:55 +00:00
return Sound ( " Hits::SoftHit? " ) ;
2012-04-03 00:55:55 +00:00
}
// Removes all objects of the given type.
2014-12-12 22:27:17 +00:00
global func RemoveAll ( p , . . . )
2012-04-03 00:55:55 +00:00
{
var cnt ;
if ( GetType ( p ) = = C4V_PropList ) p = Find_ID ( p ) ; // RemoveAll(ID) shortcut
for ( var obj in FindObjects ( p , . . . ) )
{
if ( obj )
{
obj - > RemoveObject ( ) ;
cnt + + ;
}
}
return cnt ;
}
// Splits the calling object into its components.
global func Split2Components ( )
{
if ( ! this )
return false ;
var ctr = Contained ( ) ;
// Transfer all contents to container.
while ( Contents ( ) )
if ( ! ctr | | ! Contents ( ) - > Enter ( ctr ) )
Contents ( ) - > Exit ( ) ;
// Split components.
for ( var i = 0 , compid ; compid = GetComponent ( nil , i ) ; + + i )
for ( var j = 0 ; j < GetComponent ( compid ) ; + + j )
{
2015-01-10 09:14:02 +00:00
var comp = CreateObjectAbove ( compid , nil , nil , GetOwner ( ) ) ;
2012-04-03 00:55:55 +00:00
if ( OnFire ( ) ) comp - > Incinerate ( ) ;
if ( ! ctr | | ! comp - > Enter ( ctr ) )
{
comp - > SetR ( Random ( 360 ) ) ;
comp - > SetXDir ( Random ( 3 ) - 1 ) ;
comp - > SetYDir ( Random ( 3 ) - 1 ) ;
comp - > SetRDir ( Random ( 3 ) - 1 ) ;
}
}
RemoveObject ( ) ;
return ;
2012-04-03 01:12:44 +00:00
}
// Pulls an object above ground if it was buried (e.g. by PlaceVegetation).
// The object must have 'Bottom' and 'Center' CNAT to use this.
// (bottom is the point which should be buried, center the lowest point that must not be buried)
// Mainly used by plants.
global func RootSurface ( )
{
if ( HasCNAT ( CNAT_Center ) )
{
var i = 0 ;
while ( GetContact ( - 1 ) & CNAT_Center & & i < GetObjHeight ( ) / 2 ) { SetPosition ( GetX ( ) , GetY ( ) - 1 ) ; i + + ; } //Move up if too far underground
}
if ( HasCNAT ( CNAT_Bottom ) )
{
i = 0 ;
while ( ! ( GetContact ( - 1 ) & CNAT_Bottom ) & & i < GetObjHeight ( ) / 2 ) { SetPosition ( GetX ( ) , GetY ( ) + 1 ) ; i + + ; } //Move down if in midair
if ( ! Stuck ( ) ) SetPosition ( GetX ( ) , GetY ( ) + 1 ) ; // try make the plant stuck
}
}
// Buys an object.
global func Buy ( id idBuyObj , int iForPlr , int iPayPlr , object pToBase , bool fShowErrors )
{
// if no base is given try this
if ( ! pToBase ) pToBase = this ;
// not a base?
if ( ! pToBase - > ~ IsBase ( ) )
return 0 ;
return pToBase - > DoBuy ( idBuyObj , iForPlr , iPayPlr , 0 , 0 , fShowErrors ) ;
}
// Sells an object.
global func Sell ( int iPlr , object pObj , object pToBase )
{
// if no base is given try this
if ( ! pToBase ) pToBase = this ;
// not a base?
if ( ! pToBase - > ~ IsBase ( ) )
return 0 ;
return pToBase - > DoSell ( pObj , iPlr ) ;
}
// Returns the owner if this is a base.
global func GetBase ( )
{
if ( ! ( this - > ~ IsBase ( ) ) ) return NO_OWNER ;
return GetOwner ( ) ;
2012-04-14 21:36:54 +00:00
}
/* GetXEdge returns the position of the objects top/bottom/left/right edge */
global func GetLeftEdge ( )
{
return GetX ( ) - GetObjWidth ( ) / 2 ;
}
global func GetRightEdge ( )
{
return GetX ( ) + GetObjWidth ( ) / 2 ;
}
global func GetTopEdge ( )
{
return GetY ( ) - GetObjHeight ( ) / 2 ;
}
global func GetBottomEdge ( )
{
return GetY ( ) + GetObjHeight ( ) / 2 ;
2012-05-06 16:10:16 +00:00
}
// Returns if the object is standing in front of the back-object
global func InFrontOf ( object back )
{
var front = this ;
if ( ! front )
return ;
return front - > FindObject ( front - > Find_AtPoint ( ) , Find_Not ( Find_Exclude ( back ) ) ) ! = nil ;
2012-06-05 20:51:09 +00:00
}
2015-06-08 19:06:18 +00:00
// Returns the current left of the object relative to its current position.
global func GetLeft ( )
{
var offset_x = GetObjectVal ( " Offset " , nil , 0 ) ;
if ( offset_x = = nil )
offset_x = GetDefCoreVal ( " Offset " , nil , 0 ) ;
return offset_x ;
}
// Returns the current right of the object relative to its current position.
global func GetRight ( )
{
var offset_x = GetObjectVal ( " Offset " , nil , 0 ) ;
if ( offset_x = = nil )
offset_x = GetDefCoreVal ( " Offset " , nil , 0 ) ;
var width = GetObjectVal ( " Width " ) ;
return offset_x + width ;
}
// Returns the current top of the object relative to its current position.
global func GetTop ( )
{
var offset_y = GetObjectVal ( " Offset " , nil , 1 ) ;
if ( offset_y = = nil )
offset_y = GetDefCoreVal ( " Offset " , nil , 1 ) ;
return offset_y ;
}
// Returns the current bottom of the object relative to its current position.
global func GetBottom ( )
{
var offset_y = GetObjectVal ( " Offset " , nil , 1 ) ;
if ( offset_y = = nil )
offset_y = GetDefCoreVal ( " Offset " , nil , 1 ) ;
var height = GetObjectVal ( " Height " ) ;
return offset_y + height ;
}
// Returns the current shape as an array [offset_x, offset_y, width, height].
global func GetShape ( )
{
var offset_x = GetObjectVal ( " Offset " , nil , 0 ) ;
if ( offset_x = = nil )
offset_x = GetDefCoreVal ( " Offset " , nil , 0 ) ;
var offset_y = GetObjectVal ( " Offset " , nil , 1 ) ;
if ( offset_y = = nil )
offset_y = GetDefCoreVal ( " Offset " , nil , 1 ) ;
var width = GetObjectVal ( " Width " ) ;
var height = GetObjectVal ( " Height " ) ;
return [ offset_x , offset_y , width , height ] ;
}