/***
*
* NEW file for the Mod " Spirit of Half-Life " , by Laurie R . Cheers . ( LRC )
* Created 19 / 11 / 00
*
* * */
/*
= = = = = alias . cpp = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Alias entities , replace the less powerful and ( IMHO ) less intuitive
trigger_changetarget entity .
*/
# include "extdll.h"
# include "util.h"
# include "cbase.h"
TYPEDESCRIPTION CBaseAlias : : m_SaveData [ ] =
{
DEFINE_FIELD ( CBaseAlias , m_pNextAlias , FIELD_CLASSPTR ) ,
} ;
IMPLEMENT_SAVERESTORE ( CBaseAlias , CPointEntity )
/*********************
* Worldcraft entity : info_alias
*
* targetname - alias name
* target - alias destination while ON
* netname - alias destination while OFF
* * * * * * * * * * * * * * * * * * * * * */
# define SF_ALIAS_OFF 1
# define SF_ALIAS_DEBUG 2
class CInfoAlias : public CBaseAlias
{
public :
void Use ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value ) ;
void Spawn ( void ) ;
STATE GetState ( ) { return ( pev - > spawnflags & SF_ALIAS_OFF ) ? STATE_OFF : STATE_ON ; }
CBaseEntity * FollowAlias ( CBaseEntity * pFrom ) ;
void ChangeValue ( int iszValue ) ;
void FlushChanges ( void ) ;
} ;
LINK_ENTITY_TO_CLASS ( info_alias , CInfoAlias )
void CInfoAlias : : Spawn ( void )
{
if ( pev - > spawnflags & SF_ALIAS_OFF )
pev - > message = pev - > netname ;
else
pev - > message = pev - > target ;
}
void CInfoAlias : : Use ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value )
{
if ( pev - > spawnflags & SF_ALIAS_OFF )
{
if ( pev - > spawnflags & SF_ALIAS_DEBUG )
ALERT ( at_console , " DEBUG: info_alias %s turns on \n " , STRING ( pev - > targetname ) ) ;
pev - > spawnflags & = ~ SF_ALIAS_OFF ;
pev - > noise = pev - > target ;
}
else
{
if ( pev - > spawnflags & SF_ALIAS_DEBUG )
ALERT ( at_console , " DEBUG: info_alias %s turns off \n " , STRING ( pev - > targetname ) ) ;
pev - > spawnflags | = SF_ALIAS_OFF ;
pev - > noise = pev - > netname ;
}
UTIL_AddToAliasList ( this ) ;
}
CBaseEntity * CInfoAlias : : FollowAlias ( CBaseEntity * pFrom )
{
return UTIL_FindEntityByTargetname ( pFrom , STRING ( pev - > message ) ) ;
}
void CInfoAlias : : ChangeValue ( int iszValue )
{
pev - > noise = iszValue ;
UTIL_AddToAliasList ( this ) ;
}
void CInfoAlias : : FlushChanges ( void )
{
pev - > message = pev - > noise ;
if ( pev - > spawnflags & SF_ALIAS_DEBUG )
ALERT ( at_console , " DEBUG: info_alias %s now refers to \" %s \" \n " , STRING ( pev - > targetname ) , STRING ( pev - > message ) ) ;
}
/*********************
* Worldcraft entity : info_group
*
* targetname - name
* target - alias entity to affect
* other values are handled in a multi_manager - like way .
* * * * * * * * * * * * * * * * * * * * * */
// definition in cbase.h
# define SF_GROUP_DEBUG 2
LINK_ENTITY_TO_CLASS ( info_group , CInfoGroup ) ;
TYPEDESCRIPTION CInfoGroup : : m_SaveData [ ] =
{
DEFINE_FIELD ( CInfoGroup , m_cMembers , FIELD_INTEGER ) ,
DEFINE_ARRAY ( CInfoGroup , m_iszMemberName , FIELD_STRING , MAX_MULTI_TARGETS ) ,
DEFINE_ARRAY ( CInfoGroup , m_iszMemberValue , FIELD_STRING , MAX_MULTI_TARGETS ) ,
DEFINE_FIELD ( CInfoGroup , m_iszDefaultMember , FIELD_STRING ) ,
} ;
IMPLEMENT_SAVERESTORE ( CInfoGroup , CBaseEntity ) ;
void CInfoGroup : : KeyValue ( KeyValueData * pkvd )
{
if ( FStrEq ( pkvd - > szKeyName , " defaultmember " ) )
{
m_iszDefaultMember = ALLOC_STRING ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
// this assumes that additional fields are targetnames and their values are delay values.
else if ( m_cMembers < MAX_MULTI_TARGETS )
{
char tmp [ 128 ] ;
UTIL_StripToken ( pkvd - > szKeyName , tmp ) ;
m_iszMemberName [ m_cMembers ] = ALLOC_STRING ( tmp ) ;
m_iszMemberValue [ m_cMembers ] = ALLOC_STRING ( pkvd - > szValue ) ;
m_cMembers + + ;
pkvd - > fHandled = TRUE ;
}
else
{
ALERT ( at_error , " Too many members for info_group %s (limit is %d) \n " , STRING ( pev - > targetname ) , MAX_MULTI_TARGETS ) ;
}
}
void CInfoGroup : : Use ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value )
{
CBaseEntity * pTarget = UTIL_FindEntityByTargetname ( NULL , STRING ( pev - > target ) ) ;
if ( pTarget & & pTarget - > IsAlias ( ) )
{
if ( pev - > spawnflags & SF_GROUP_DEBUG )
ALERT ( at_console , " DEBUG: info_group %s changes the contents of %s \" %s \" \n " , STRING ( pev - > targetname ) , STRING ( pTarget - > pev - > classname ) , STRING ( pTarget - > pev - > targetname ) ) ;
( ( CBaseAlias * ) pTarget ) - > ChangeValue ( this ) ;
}
else if ( pev - > target )
{
ALERT ( at_console , " info_group \" %s \" : alias \" %s \" was not found or not an alias! " , STRING ( pev - > targetname ) , STRING ( pev - > target ) ) ;
}
}
int CInfoGroup : : GetMember ( const char * szMemberName )
{
if ( ! szMemberName )
{
ALERT ( at_console , " info_group: GetMember called with null szMemberName!? \n " ) ;
return 0 ;
}
for ( int i = 0 ; i < m_cMembers ; i + + )
{
if ( FStrEq ( szMemberName , STRING ( m_iszMemberName [ i ] ) ) )
{
// ALERT(at_console,"getMember: found member\n");
return m_iszMemberValue [ i ] ;
}
}
if ( m_iszDefaultMember )
{
static char szBuffer [ 128 ] ;
strcpy ( szBuffer , STRING ( m_iszDefaultMember ) ) ;
strcat ( szBuffer , szMemberName ) ;
return MAKE_STRING ( szBuffer ) ;
// this is a messy way to do it... but currently, only one
// GetMember gets performed at a time, so it works.
}
ALERT ( at_console , " info_group \" %s \" has no member called \" %s \" . \n " , STRING ( pev - > targetname ) , szMemberName ) ;
// ALERT(at_console,"getMember: fail\n");
return 0 ;
}
/*********************
* Worldcraft entity : multi_alias
*
* targetname - name
* other values are handled in a multi_manager - like way .
* * * * * * * * * * * * * * * * * * * * * */
// definition in cbase.h
LINK_ENTITY_TO_CLASS ( multi_alias , CMultiAlias ) ;
TYPEDESCRIPTION CMultiAlias : : m_SaveData [ ] =
{
DEFINE_FIELD ( CMultiAlias , m_cTargets , FIELD_INTEGER ) ,
DEFINE_ARRAY ( CMultiAlias , m_iszTargets , FIELD_STRING , MAX_MULTI_TARGETS ) ,
DEFINE_FIELD ( CMultiAlias , m_iTotalValue , FIELD_INTEGER ) ,
DEFINE_ARRAY ( CMultiAlias , m_iValues , FIELD_INTEGER , MAX_MULTI_TARGETS ) ,
DEFINE_FIELD ( CMultiAlias , m_iMode , FIELD_INTEGER ) ,
} ;
IMPLEMENT_SAVERESTORE ( CMultiAlias , CBaseAlias ) ;
void CMultiAlias : : KeyValue ( KeyValueData * pkvd )
{
if ( FStrEq ( pkvd - > szKeyName , " m_iMode " ) )
{
m_iMode = atoi ( pkvd - > szValue ) ;
pkvd - > fHandled = TRUE ;
}
// this assumes that additional fields are targetnames and their values are probability values.
else if ( m_cTargets < MAX_MULTI_TARGETS )
{
char tmp [ 128 ] ;
UTIL_StripToken ( pkvd - > szKeyName , tmp ) ;
m_iszTargets [ m_cTargets ] = ALLOC_STRING ( tmp ) ;
m_iValues [ m_cTargets ] = atoi ( pkvd - > szValue ) ;
m_iTotalValue + = m_iValues [ m_cTargets ] ;
m_cTargets + + ;
pkvd - > fHandled = TRUE ;
}
else
{
ALERT ( at_error , " Too many targets for multi_alias %s (limit is %d) \n " , STRING ( pev - > targetname ) , MAX_MULTI_TARGETS ) ;
}
}
CBaseEntity * CMultiAlias : : FollowAlias ( CBaseEntity * pStartEntity )
{
CBaseEntity * pBestEntity = NULL ; // the entity we're currently planning to return.
int iBestOffset = - 1 ; // the offset of that entity.
CBaseEntity * pTempEntity ;
int iTempOffset ;
int i = 0 ;
if ( m_iMode )
{
// During any given 'game moment', this code may be called more than once. It must use the
// same random values each time (because otherwise it gets really messy). I'm using srand
// to arrange this.
srand ( ( int ) ( gpGlobals - > time * 100 ) ) ;
rand ( ) ; // throw away the first result - it's just the seed value
if ( m_iMode = = 1 ) // 'choose one' mode
{
int iRandom = 1 + ( rand ( ) % m_iTotalValue ) ;
for ( i = 0 ; i < m_cTargets ; i + + )
{
iRandom - = m_iValues [ i ] ;
if ( iRandom < = 0 )
break ;
}
}
else // 'percent chance' mode
{
for ( i = 0 ; i < m_cTargets ; i + + )
{
if ( m_iValues [ i ] > = rand ( ) % 100 )
break ;
}
}
}
while ( i < m_cTargets )
{
pTempEntity = UTIL_FindEntityByTargetname ( pStartEntity , STRING ( m_iszTargets [ i ] ) ) ;
if ( pTempEntity )
{
// We've found an entity; only use it if its offset is lower than the offset we've currently got.
iTempOffset = OFFSET ( pTempEntity - > pev ) ;
if ( iBestOffset = = - 1 | | iTempOffset < iBestOffset )
{
iBestOffset = iTempOffset ;
pBestEntity = pTempEntity ;
}
}
if ( m_iMode = = 1 )
break ; // if it's in "pick one" mode, stop after the first.
else if ( m_iMode = = 2 )
{
i + + ;
// if it's in "percent chance" mode, try to find another one to fire.
while ( i < m_cTargets )
{
if ( m_iValues [ i ] > rand ( ) % 100 )
break ;
i + + ;
}
}
else
i + + ;
}
return pBestEntity ;
}
/*********************
* Worldcraft entity : trigger_changealias
*
* target - alias entity to affect
* netname - value to change the alias to
* * * * * * * * * * * * * * * * * * * * * */
# define SF_CHANGEALIAS_RESOLVE 1
# define SF_CHANGEALIAS_DEBUG 2
class CTriggerChangeAlias : public CBaseEntity
{
public :
void Spawn ( void ) ;
void Use ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value ) ;
int ObjectCaps ( void ) { return CBaseEntity : : ObjectCaps ( ) & ~ FCAP_ACROSS_TRANSITION ; }
} ;
LINK_ENTITY_TO_CLASS ( trigger_changealias , CTriggerChangeAlias )
void CTriggerChangeAlias : : Spawn ( void )
{
}
void CTriggerChangeAlias : : Use ( CBaseEntity * pActivator , CBaseEntity * pCaller , USE_TYPE useType , float value )
{
CBaseEntity * pTarget = UTIL_FindEntityByTargetname ( NULL , STRING ( pev - > target ) , pActivator ) ;
if ( pTarget & & pTarget - > IsAlias ( ) )
{
CBaseEntity * pValue = NULL ;
if ( FStrEq ( STRING ( pev - > netname ) , " *locus " ) )
{
pValue = pActivator ;
}
else if ( pev - > spawnflags & SF_CHANGEALIAS_RESOLVE )
{
pValue = UTIL_FollowReference ( NULL , STRING ( pev - > netname ) ) ;
}
if ( pValue )
( ( CBaseAlias * ) pTarget ) - > ChangeValue ( pValue ) ;
else
( ( CBaseAlias * ) pTarget ) - > ChangeValue ( pev - > netname ) ;
}
else
{
ALERT ( at_error , " trigger_changealias %s: alias \" %s \" was not found or not an alias! " , STRING ( pev - > targetname ) , STRING ( pev - > target ) ) ;
}
}