ef2gamesource/dlls/game/scriptslave.cpp

2702 lines
55 KiB
C++
Raw Normal View History

2012-12-30 16:37:54 +00:00
//-----------------------------------------------------------------------------
//
// $Logfile:: /EF2/Code/DLLs/game/scriptslave.cpp $
// $Revision:: 64 $
// $Author:: Singlis $
// $Date:: 9/26/03 2:36p $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
//
// DESCRIPTION:
// Standard scripted objects. Controlled by ScriptThread. These objects
// are bmodel objects created in the editor and controlled by an external
// text based script. Commands are interpretted on by one and executed
// upon a signal from the script master. The base script object can
// perform several different relative and specific rotations and translations
// and can cause other parts of the script to be executed when touched, damaged,
// touched, or used.
//
#include "_pch_cpp.h"
#include "class.h"
#include "mover.h"
#include "scriptmaster.h"
#include "scriptslave.h"
#include "sentient.h"
#include "item.h"
#include "gibs.h"
#include "explosion.h"
#include "equipment.h"
#include <qcommon/gameplaymanager.h>
/*****************************************************************************/
/*QUAKED script_object (0 0.5 1) ? NOT_SOLID
******************************************************************************/
Event EV_ScriptSlave_DoMove
(
"processCommands",
EV_CODEONLY,
NULL,
NULL,
"Move the script slave."
);
Event EV_ScriptSlave_NewOrders
(
"newOrders",
EV_CODEONLY,
NULL,
NULL,
"Inform script that it is about to get new orders."
);
Event EV_ScriptSlave_Angles
(
"angles",
EV_SCRIPTONLY,
"v",
"angles",
"Sets the angles."
);
Event EV_ScriptSlave_Trigger
(
"trigger",
EV_SCRIPTONLY,
"s",
"entname",
"Trigger entities target."
);
Event EV_ScriptSlave_Next
(
"next",
EV_DEFAULT,
NULL,
NULL,
"Goto the next waypoint."
);
Event EV_ScriptSlave_JumpTo
(
"jumpto",
EV_SCRIPTONLY,
"sFF",
"vector_or_entity token token",
"Jump to specified vector or entity."
);
Event EV_ScriptSlave_MoveTo
(
"moveto",
EV_SCRIPTONLY,
"e",
"entity_to_move_to",
"Move to the specified entity."
);
Event EV_ScriptSlave_MoveToPosition
(
"movetopos",
EV_SCRIPTONLY,
"v",
"position",
"Move to the specified position."
);
Event EV_ScriptSlave_Speed
(
"speed",
EV_DEFAULT,
"f",
"speed",
"Sets the speed."
);
Event EV_ScriptSlave_Time
(
"time",
EV_SCRIPTONLY,
"f",
"travel_time",
"Sets the travel time."
);
Event EV_ScriptSlave_MoveUp
(
"moveUp",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position up."
);
Event EV_ScriptSlave_MoveDown
(
"moveDown",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position down."
);
Event EV_ScriptSlave_MoveNorth
(
"moveNorth",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position north."
);
Event EV_ScriptSlave_MoveSouth
(
"moveSouth",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position south."
);
Event EV_ScriptSlave_MoveEast
(
"moveEast",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position east."
);
Event EV_ScriptSlave_MoveWest
(
"moveWest",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position west."
);
Event EV_ScriptSlave_MoveForward
(
"moveForward",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position forward."
);
Event EV_ScriptSlave_MoveBackward
(
"moveBackward",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position backward."
);
Event EV_ScriptSlave_MoveLeft
(
"moveLeft",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position left."
);
Event EV_ScriptSlave_MoveRight
(
"moveRight",
EV_SCRIPTONLY,
"f",
"dist",
"Move the position right."
);
Event EV_ScriptSlave_RotateXDownTo
(
"rotateXdownto",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the x down to angle."
);
Event EV_ScriptSlave_RotateYDownTo
(
"rotateYdownto",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the y down to angle."
);
Event EV_ScriptSlave_RotateZDownTo
(
"rotateZdownto",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the z down to angle."
);
Event EV_ScriptSlave_RotateAxisDownTo
(
"rotateaxisdownto",
EV_SCRIPTONLY,
"if",
"axis angle",
"Rotate the specified axis down to angle."
);
Event EV_ScriptSlave_RotateXUpTo
(
"rotateXupto",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the x up to angle."
);
Event EV_ScriptSlave_RotateYUpTo
(
"rotateYupto",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the y up to angle."
);
Event EV_ScriptSlave_RotateZUpTo
(
"rotateZupto",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the z up to angle."
);
Event EV_ScriptSlave_RotateAxisUpTo
(
"rotateaxisupto",
EV_SCRIPTONLY,
"if",
"axis angle",
"Rotate the specified axis up to angle."
);
Event EV_ScriptSlave_RotateXDown
(
"rotateXdown",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the x down by the specified amount."
);
Event EV_ScriptSlave_RotateYDown
(
"rotateYdown",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the y down by the specified amount."
);
Event EV_ScriptSlave_RotateZDown
(
"rotateZdown",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the z down by the specified amount."
);
Event EV_ScriptSlave_RotateAxisDown
(
"rotateaxisdown",
EV_SCRIPTONLY,
"if",
"axis angle",
"Rotate the specified axis down by the specified amount."
);
Event EV_ScriptSlave_RotateXUp
(
"rotateXup",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the x up by the specified amount."
);
Event EV_ScriptSlave_RotateYUp
(
"rotateYup",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the y up by the specified amount."
);
Event EV_ScriptSlave_RotateZUp
(
"rotateZup",
EV_SCRIPTONLY,
"f",
"angle",
"Rotate the z up by the specified amount."
);
Event EV_ScriptSlave_RotateAxisUp
(
"rotateaxisup",
EV_SCRIPTONLY,
"if",
"axis angle",
"Rotate the specified axis up by the specified amount."
);
Event EV_ScriptSlave_RotateX
(
"rotateX",
EV_SCRIPTONLY,
"f",
"avelocity",
"Rotate about the x axis at the specified angular velocity."
);
Event EV_ScriptSlave_RotateY
(
"rotateY",
EV_SCRIPTONLY,
"f",
"avelocity",
"Rotate about the y axis at the specified angular velocity."
);
Event EV_ScriptSlave_RotateZ
(
"rotateZ",
EV_SCRIPTONLY,
"f",
"avelocity",
"Rotate about the z axis at the specified angular velocity."
);
Event EV_ScriptSlave_RotateAxis
(
"rotateaxis",
EV_SCRIPTONLY,
"if",
"axis avelocity",
"Rotate about the specified axis at the specified angular velocity."
);
Event EV_ScriptSlave_RotateDownTo
(
"rotatedownto",
EV_SCRIPTONLY,
"v",
"direction",
"Rotate down to the specified direction."
);
Event EV_ScriptSlave_RotateUpTo
(
"rotateupto",
EV_SCRIPTONLY,
"v",
"direction",
"Rotate up to the specified direction."
);
Event EV_ScriptSlave_RotateTo
(
"rotateto",
EV_SCRIPTONLY,
"v",
"direction",
"Rotate to the specified direction."
);
Event EV_ScriptSlave_OnTouch
(
"ontouch",
EV_SCRIPTONLY,
"s",
"label",
"Sets what label to jump to and process script at when touched."
);
Event EV_ScriptSlave_NoTouch
(
"notouch",
EV_SCRIPTONLY,
NULL,
NULL,
"Removes the ontouch thread."
);
Event EV_ScriptSlave_OnUse
(
"onuse",
EV_SCRIPTONLY,
"s",
"label",
"Sets what label to jump to and process script at when used."
);
Event EV_ScriptSlave_NoUse
(
"nouse",
EV_SCRIPTONLY,
NULL,
NULL,
"Removes the onuse thread."
);
Event EV_ScriptSlave_OnBlock
(
"onblock",
EV_SCRIPTONLY,
"s",
"label",
"Sets what label to jump to and process script at when blocked."
);
Event EV_ScriptSlave_NoBlock
(
"noblock",
EV_SCRIPTONLY,
NULL,
NULL,
"Removes the onblock thread."
);
Event EV_ScriptSlave_OnTrigger
(
"ontrigger",
EV_SCRIPTONLY,
"s",
"label",
"Sets what label to jump to and process script at when triggered."
);
Event EV_ScriptSlave_NoTrigger
(
"notrigger",
EV_SCRIPTONLY,
NULL,
NULL,
"Removes the ontrigger thread."
);
Event EV_ScriptSlave_OnDamage
(
"ondamage",
EV_SCRIPTONLY,
"s",
"label",
"Sets what label to jump to and process script at when damaged."
);
Event EV_ScriptSlave_NoDamage
(
"nodamage",
EV_DEFAULT,
NULL,
NULL,
"Removes the ondamage thread."
);
Event EV_ScriptSlave_SetMeansOfDeath
(
"setmeansofdeath",
EV_SCRIPTONLY,
"s",
"means_of_death",
"Set the damage means of death."
);
Event EV_ScriptSlave_SetDamageSpawn
(
"dmg",
EV_SCRIPTONLY,
"f",
"damage",
"Set the damage."
);
Event EV_ScriptSlave_FollowPath
(
"followpath",
EV_SCRIPTONLY,
"eSSSSSS",
"path arg1 arg2 arg3 arg4 arg5 arg6",
"Makes the script slave follow the specified path. The allowable arguments are ignoreangles,\n"
"normalangles, loop, and a number specifying the start time."
);
Event EV_ScriptSlave_EndPath
(
"endpath",
EV_SCRIPTONLY,
NULL,
NULL,
"Stop following the path"
);
Event EV_ScriptSlave_MoveDone
(
"scriptslave_movedone",
EV_CODEONLY,
NULL,
NULL,
"Called when the script slave is doen moving"
);
Event EV_ScriptSlave_FollowingPath
(
"scriptslave_followingpath",
EV_CODEONLY,
NULL,
NULL,
"Called every frame to actually follow the path"
);
Event EV_ScriptSlave_Explode
(
"scriptSlave_explode",
EV_SCRIPTONLY,
"f",
"damage",
"Creates an explosion at the script slave's position"
);
Event EV_ScriptSlave_NotShootable
(
"notshootable",
EV_SCRIPTONLY,
NULL,
NULL,
"Makes the script slave not shootable"
);
Event EV_ScriptSlave_OpenAreaPortal
(
"openportal",
EV_SCRIPTONLY,
NULL,
NULL,
"Open the area portal enclosed in this object"
);
Event EV_ScriptSlave_CloseAreaPortal
(
"closeportal",
EV_SCRIPTONLY,
NULL,
NULL,
"Close the area portal enclosed in this object"
);
Event EV_ScriptSlave_PhysicsOn
(
"physics_on",
EV_SCRIPTONLY,
NULL,
NULL,
"Turn physics on this script object on"
);
Event EV_ScriptSlave_PhysicsOff
(
"physics_off",
EV_SCRIPTONLY,
NULL,
NULL,
"Turn physics off this script object on"
);
Event EV_ScriptSlave_PhysicsVelocity
(
"physics_velocity",
EV_SCRIPTONLY,
"v",
"impulseVector",
"Add a physical impulse to an object when it is being physically simulated"
);
Event EV_ScriptSlave_StopEvent
(
"stopspline",
EV_SCRIPTONLY,
NULL,
NULL,
"stops an scriptobject from moving on a spline"
);
Event EV_ScriptSlave_ContinueEvent
(
"continuespline",
EV_SCRIPTONLY,
NULL,
NULL,
"makes a script object continue on a spline"
);
// 1ST PLAYABLE HACK
Event EV_ScriptSlave_Hack_SetTriggerParms
(
"setobjectparms",
EV_DEFAULT,
"ff",
"force_field_number trigger_number",
"HACK HACK HACK HACK HACK HACK HACK"
);
Event EV_ScriptSlave_Hack_GetForceFieldNumber
(
"getforcefieldnumber",
EV_DEFAULT,
"@f",
"number",
"HACK HACK HACK HACK HACK HACK HACK"
);
Event EV_ScriptSlave_Hack_GetTriggerNumber
(
"gettriggernumber",
EV_DEFAULT,
"@f",
"number",
"HACK HACK HACK HACK HACK HACK HACK"
);
Event EV_ScriptSlave_Hack_GetScanner
(
"getscanner",
EV_DEFAULT,
"@e",
"scanner",
"HACK HACK HACK HACK HACK HACK HACK"
);
Event EV_ScriptSlave_HandlesDamage
(
"handlesdamage",
EV_DEFAULT,
"b",
"damage_flag",
"sets the handlesdamage flag on the script slave"
);
Event EV_ScriptSlave_DamageEffect
(
"damageEffect",
EV_DEFAULT,
"s",
"damageEffectModel",
"Sets the damage effect model name."
);
Event EV_ScriptSlave_BloodModel
(
"setBloodModel",
EV_DEFAULT,
"s",
"bloodmodel",
"Sets the blood model"
);
Event EV_ScriptSlave_AddRequiredDamageMOD
(
"addrequireddamagemod",
EV_DEFAULT,
"s",
"MOD_String",
"Adds the required MOD for damage to be applied"
);
Event EV_ScriptSlave_SetCanBeAttackedByOtherScriptObjects
(
"allowAttackFromOtherScriptObjects",
EV_DEFAULT,
"b",
"allow_flag",
"Sets the _canBeAttackedByOtherScriptSlaves variable"
);
CLASS_DECLARATION( Trigger, ScriptSlave, "script_object" )
{
{ &EV_Bind, &ScriptSlave::BindEvent },
{ &EV_Unbind, &ScriptSlave::EventUnbind },
{ &EV_ScriptSlave_DoMove, &ScriptSlave::DoMove },
{ &EV_ScriptSlave_NewOrders, &ScriptSlave::NewOrders },
{ &EV_ScriptSlave_Angles, &ScriptSlave::SetAnglesEvent },
{ &EV_SetAngle, &ScriptSlave::SetAngleEvent },
{ &EV_Model, &ScriptSlave::SetModelEvent },
{ &EV_ScriptSlave_Trigger, &ScriptSlave::TriggerEvent },
{ &EV_ScriptSlave_Next, &ScriptSlave::GotoNextWaypoint },
{ &EV_ScriptSlave_JumpTo, &ScriptSlave::JumpTo },
{ &EV_ScriptSlave_MoveTo, &ScriptSlave::MoveToEvent },
{ &EV_ScriptSlave_MoveToPosition, &ScriptSlave::MoveToPositionEvent },
{ &EV_ScriptSlave_Speed, &ScriptSlave::SetSpeed },
{ &EV_ScriptSlave_Time, &ScriptSlave::SetTime },
{ &EV_ScriptSlave_MoveUp, &ScriptSlave::MoveUp },
{ &EV_ScriptSlave_MoveDown, &ScriptSlave::MoveDown },
{ &EV_ScriptSlave_MoveNorth, &ScriptSlave::MoveNorth },
{ &EV_ScriptSlave_MoveSouth, &ScriptSlave::MoveSouth },
{ &EV_ScriptSlave_MoveEast, &ScriptSlave::MoveEast },
{ &EV_ScriptSlave_MoveWest, &ScriptSlave::MoveWest },
{ &EV_ScriptSlave_MoveForward, &ScriptSlave::MoveForward },
{ &EV_ScriptSlave_MoveBackward, &ScriptSlave::MoveBackward },
{ &EV_ScriptSlave_MoveLeft, &ScriptSlave::MoveLeft },
{ &EV_ScriptSlave_MoveRight, &ScriptSlave::MoveRight },
{ &EV_ScriptSlave_RotateXDownTo, &ScriptSlave::RotateXdownto },
{ &EV_ScriptSlave_RotateYDownTo, &ScriptSlave::RotateYdownto },
{ &EV_ScriptSlave_RotateZDownTo, &ScriptSlave::RotateZdownto },
{ &EV_ScriptSlave_RotateXUpTo, &ScriptSlave::RotateXupto },
{ &EV_ScriptSlave_RotateYUpTo, &ScriptSlave::RotateYupto },
{ &EV_ScriptSlave_RotateZUpTo, &ScriptSlave::RotateZupto },
{ &EV_ScriptSlave_RotateXDown, &ScriptSlave::RotateXdown },
{ &EV_ScriptSlave_RotateYDown, &ScriptSlave::RotateYdown },
{ &EV_ScriptSlave_RotateZDown, &ScriptSlave::RotateZdown },
{ &EV_ScriptSlave_RotateXUp, &ScriptSlave::RotateXup },
{ &EV_ScriptSlave_RotateYUp, &ScriptSlave::RotateYup },
{ &EV_ScriptSlave_RotateZUp, &ScriptSlave::RotateZup },
{ &EV_ScriptSlave_RotateX, &ScriptSlave::RotateX },
{ &EV_ScriptSlave_RotateY, &ScriptSlave::RotateY },
{ &EV_ScriptSlave_RotateZ, &ScriptSlave::RotateZ },
{ &EV_ScriptSlave_RotateAxisDownTo, &ScriptSlave::RotateAxisdownto },
{ &EV_ScriptSlave_RotateAxisUpTo, &ScriptSlave::RotateAxisupto },
{ &EV_ScriptSlave_RotateAxisDown, &ScriptSlave::RotateAxisdown },
{ &EV_ScriptSlave_RotateAxisUp, &ScriptSlave::RotateAxisup },
{ &EV_ScriptSlave_RotateAxis, &ScriptSlave::RotateZ },
{ &EV_ScriptSlave_OnTouch, &ScriptSlave::OnTouch },
{ &EV_ScriptSlave_NoTouch, &ScriptSlave::NoTouch },
{ &EV_ScriptSlave_OnUse, &ScriptSlave::OnUse },
{ &EV_ScriptSlave_NoUse, &ScriptSlave::NoUse },
{ &EV_ScriptSlave_OnBlock, &ScriptSlave::OnBlock },
{ &EV_ScriptSlave_NoBlock, &ScriptSlave::NoBlock },
{ &EV_ScriptSlave_OnTrigger, &ScriptSlave::OnTrigger },
{ &EV_ScriptSlave_NoTrigger, &ScriptSlave::NoTrigger },
{ &EV_ScriptSlave_OnDamage, &ScriptSlave::OnDamage },
{ &EV_ScriptSlave_NoDamage, &ScriptSlave::NoDamage },
{ &EV_ScriptSlave_SetMeansOfDeath, &ScriptSlave::SetMeansOfDeath },
{ &EV_ScriptSlave_SetDamageSpawn, &ScriptSlave::SetDamage },
{ &EV_ScriptSlave_FollowPath, &ScriptSlave::FollowPath },
{ &EV_ScriptSlave_EndPath, &ScriptSlave::EndPath },
{ &EV_ScriptSlave_FollowingPath, &ScriptSlave::FollowingPath },
{ &EV_Touch, &ScriptSlave::TouchFunc },
{ &EV_Blocked, &ScriptSlave::BlockFunc },
{ &EV_Activate, &ScriptSlave::TriggerFunc },
{ &EV_Use, &ScriptSlave::UseFunc },
{ &EV_ScriptSlave_MoveDone, &ScriptSlave::MoveEnd },
{ &EV_Damage, &ScriptSlave::DamageFunc },
{ &EV_ScriptSlave_RotateDownTo, &ScriptSlave::Rotatedownto },
{ &EV_ScriptSlave_RotateUpTo, &ScriptSlave::Rotateupto },
{ &EV_ScriptSlave_RotateTo, &ScriptSlave::Rotateto },
{ &EV_ScriptSlave_Explode, &ScriptSlave::Explode },
{ &EV_ScriptSlave_NotShootable, &ScriptSlave::NotShootable },
{ &EV_ScriptSlave_OpenAreaPortal, &ScriptSlave::OpenPortal },
{ &EV_ScriptSlave_CloseAreaPortal, &ScriptSlave::ClosePortal },
{ &EV_ScriptSlave_PhysicsOn, &ScriptSlave::PhysicsOn },
{ &EV_ScriptSlave_PhysicsOff, &ScriptSlave::PhysicsOff },
{ &EV_ScriptSlave_PhysicsVelocity, &ScriptSlave::PhysicsVelocity },
{ &EV_ScriptSlave_StopEvent, &ScriptSlave::StopEvent },
{ &EV_ScriptSlave_ContinueEvent, &ScriptSlave::ContinueEvent },
{ &EV_SetGameplayDamage, &ScriptSlave::setDamage },
{ &EV_ScriptSlave_HandlesDamage, &ScriptSlave::HandlesDamage },
{ &EV_ScriptSlave_DamageEffect, &ScriptSlave::setDamageEffect },
{ &EV_ScriptSlave_BloodModel, &ScriptSlave::setBloodModel },
{ &EV_ScriptSlave_AddRequiredDamageMOD, &ScriptSlave::addRequiredDamageMOD },
{ &EV_ScriptSlave_SetCanBeAttackedByOtherScriptObjects, &ScriptSlave::setCanBeAttackedByOtherSlaves },
//1ST PLAYABLE HACK STUFF
{ &EV_ScriptSlave_Hack_SetTriggerParms, &ScriptSlave::Hack_AddParms },
{ &EV_ScriptSlave_Hack_GetForceFieldNumber, &ScriptSlave::Hack_GetForceFieldNumber },
{ &EV_ScriptSlave_Hack_GetTriggerNumber, &ScriptSlave::Hack_GetTriggerNumber },
{ &EV_ScriptSlave_Hack_GetScanner, &ScriptSlave::Hack_GetScanner },
{ NULL, NULL }
};
ScriptSlave::ScriptSlave()
{
mover = new Mover( this );
if ( LoadingSavegame )
{
// Archive function will setup all necessary data
return;
}
// this is a normal entity
edict->s.eType = ET_GENERAL;
speed = 100;
takedamage = DAMAGE_YES;
waypoint = NULL;
SetNewAngles( localangles );
SetNewPosition( GetLocalOrigin() );
traveltime = 0;
commandswaiting = false;
movethread = NULL;
touchthread = NULL;
blockthread = NULL;
damagethread = NULL;
triggerthread = NULL;
usethread = NULL;
splinePath = NULL;
splineangles = false;
attack_finished = 0;
thinking = true;
dmg = 2;
dmg_means_of_death = MOD_CRUSH;
setMoveType( MOVETYPE_PUSH );
setSolidType( SOLID_NOT );
//1ST PLAYABLE HACK
_forcefieldNumber = -1.0f;
_triggerNumber = -1.0f;
_scanner = NULL;
_portalOpen = false;
_handlesDamage = false;
_nextNeedToUseTime = 0.0f;
_canBeAttackedByOtherScriptSlaves = true;
if ( spawnflags & 1 )
{
PostEvent( EV_BecomeNonSolid, EV_POSTSPAWN );
}
}
ScriptSlave::~ScriptSlave()
{
if ( splinePath )
{
delete splinePath;
splinePath = NULL;
}
}
//--------------------------------------------------------------
//
// Name: setDamage
// Class: ScriptSlave
//
// Description: This function acts as a filter to the real function.
// It gets data from the database, and then passes it
// along to the original event. This is here as an attempt
// to sway people into using the database standard instead of
// hardcoded numbers.
//
// Parameters: Event *ev
// str -- The value keyword from the database (low, medium, high, etc).
//
// Returns: None
//
//--------------------------------------------------------------
void ScriptSlave::setDamage( Event *ev )
{
if ( ev->NumArgs() < 1 )
return;
GameplayManager *gpm = GameplayManager::getTheGameplayManager();
if ( !gpm->hasFormula("OffensiveDamage") )
return;
str damagestr = ev->GetString( 1 );
float damagemod = 1.0f;
if ( gpm->getDefine(damagestr) != "" )
damagemod = (float)atof(gpm->getDefine(damagestr));
GameplayFormulaData fd(this, 0, 0, "");
float finaldamage = gpm->calculate("OffensiveDamage", fd, damagemod);
Event *newev = new Event(EV_ScriptSlave_SetDamageSpawn);
newev->AddFloat(finaldamage);
ProcessEvent(newev);
}
void ScriptSlave::setOrigin( const Vector &point )
{
Trigger::setOrigin( point );
SetNewPosition( GetLocalOrigin() );
}
void ScriptSlave::setOrigin( void )
{
Trigger::setOrigin();
SetNewPosition( GetLocalOrigin() );
}
void ScriptSlave::NewOrders( Event *ev )
{
// make sure position and angles are current
SetNewAngles( localangles );
SetNewPosition( GetLocalOrigin() );
}
void ScriptSlave::BindEvent( Event *ev )
{
Entity *ent;
ent = ev->GetEntity( 1 );
if ( ent )
{
bind( ent );
}
// make sure position and angles are current
SetNewAngles( localangles );
SetNewPosition( GetLocalOrigin() );
}
void ScriptSlave::EventUnbind( Event *ev )
{
unbind();
// make sure position and angles are current
SetNewAngles( localangles );
SetNewPosition( GetLocalOrigin() );
}
void ScriptSlave::DoMove( Event *ev )
{
float dist;
CThread *thread;
Event *event;
thread = ev->GetThread();
assert( thread );
if ( thread && thread->WaitingFor( this ) )
{
if ( movethread && ( movethread != thread ) )
{
// warn the user
ev->Error( "Overriding previous move commands for '%s'\n", TargetName() );
// Yeah, we're not REALLY done, but we tell our old thread
// that we are so that it doesn't wait forever
event = new Event( EV_MoveDone );
event->AddEntity( this );
movethread->ProcessEvent( event );
}
movethread = thread;
}
if ( commandswaiting )
{
if ( splinePath )
{
moving = true;
PostEvent( EV_ScriptSlave_FollowingPath, 0.0f );
}
else
{
float t = traveltime;
if ( t == 0.0f )
{
dist = Vector( GetNewPosition() - GetLocalOrigin() ).length();
t = dist / speed;
}
moving = true;
mover->LinearInterpolate( GetNewPosition(), GetNewAngles(), t, EV_ScriptSlave_MoveDone );
}
commandswaiting = false;
}
else if ( movethread && ( movethread == thread ) && !moving )
{
// No commands, so tell the master that we're done
PostEvent( EV_ScriptSlave_MoveDone, 0.0f );
}
}
void ScriptSlave::MoveEnd( Event *ev )
{
Event *event;
moving = false;
commandswaiting = false;
SetNewAngles( localangles );
SetNewPosition( GetLocalOrigin() );
if ( movethread )
{
event = new Event( EV_MoveDone );
event->AddEntity( this );
movethread->ProcessEvent( event );
movethread = NULL;
}
}
void ScriptSlave::SetAnglesEvent( Event *ev )
{
commandswaiting = true;
setAngles( ev->GetVector( 1 ) );
SetNewAngles( localangles );
}
void ScriptSlave::SetAngleEvent( Event *ev )
{
float angle;
angle = ev->GetFloat( 1 );
if ( angle == -1.0f )
{
ForwardDir = Vector( 0.0f, 0.0f, 90.0f );
}
else if ( angle == -2.0f )
{
ForwardDir = Vector( 0.0f, 0.0f, -90.0f );
}
else
{
ForwardDir = Vector( 0.0f, angle, 0.0f );
}
}
void ScriptSlave::SetModelEvent( Event *ev )
{
const char *m;
m = ev->GetString( 1 );
setModel( m );
showModel();
if ( !edict->s.modelindex )
{
hideModel();
setSolidType( SOLID_NOT );
}
else if ( !m || strstr( m, ".tik" ) )
{
setSolidType( SOLID_BBOX );
}
else if ( strstr( m, ".spr" ) )
{
setSolidType( SOLID_NOT );
}
else
{
setSolidType( SOLID_BSP );
}
}
void ScriptSlave::TriggerEvent( Event *ev )
{
Entity *ent;
Event *e;
str name;
name = ev->GetString(1);
ent = G_FindTarget(NULL, name);
if ( ent )
{
SetTarget( ent->TargetName() );
e = new Event( EV_Trigger_ActivateTargets );
//fixme
//get "other"
e->AddEntity( world );
ProcessEvent( e );
}
else
{
gi.WDPrintf( "Invalid entity reference '%s'.\n", name.c_str() );
}
}
void ScriptSlave::GotoNextWaypoint( Event *ev )
{
commandswaiting = true;
if ( !waypoint )
{
ev->Error( "%s is currently not at a waypoint", TargetName() );
return;
}
waypoint = ( Waypoint * )G_FindTarget( NULL, waypoint->Target() );
if ( !waypoint )
{
ev->Error( "%s could not find waypoint %s", TargetName(), waypoint->Target() );
return;
}
else
{
SetNewPosition( waypoint->origin );
}
}
void ScriptSlave::JumpTo( Event *ev )
{
Entity *part;
//
// see if it is a vector
//
if ( ev->IsVectorAt( 1 ) )
{
SetNewPosition( ev->GetVector( 1 ) );
if ( bind_info && bind_info->bindmaster )
{
SetLocalOrigin( bind_info->bindmaster->getLocalVector( GetNewPosition() - bind_info->bindmaster->origin ) );
}
else
{
SetLocalOrigin( GetNewPosition() );
}
part = this;
while( part )
{
part->setOrigin();
part->origin.copyTo( part->edict->s.origin2 );
part->edict->s.renderfx |= RF_FRAMELERP;
if ( part->bind_info )
part = part->bind_info->teamchain;
else
part = NULL;
}
}
else
{
waypoint = ( Waypoint * )ev->GetEntity( 1 );
if ( waypoint )
{
SetNewPosition( waypoint->GetLocalOrigin() );
if ( bind_info && bind_info->bindmaster )
{
SetLocalOrigin( bind_info->bindmaster->getLocalVector( GetNewPosition() - bind_info->bindmaster->origin ) );
}
else
{
SetLocalOrigin( GetNewPosition() );
}
part = this;
while( part )
{
part->setOrigin();
part->origin.copyTo( part->edict->s.origin2 );
part->edict->s.renderfx |= RF_FRAMELERP;
if ( part->bind_info )
part = part->bind_info->teamchain;
else
part = NULL;
}
}
}
}
void ScriptSlave::MoveToEvent( Event *ev )
{
commandswaiting = true;
waypoint = ( Waypoint * )ev->GetEntity( 1 );
if ( waypoint )
{
SetNewPosition( waypoint->origin );
}
}
void ScriptSlave::MoveToPositionEvent( Event *ev )
{
commandswaiting = true;
SetNewPosition( ev->GetVector( 1 ) );
}
void ScriptSlave::SetSpeed( Event *ev )
{
speed = ev->GetFloat( 1 );
traveltime = 0;
}
void ScriptSlave::SetTime( Event *ev )
{
traveltime = ev->GetFloat( 1 );
}
// Relative move commands
void ScriptSlave::MoveUp( Event *ev )
{
commandswaiting = true;
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y, GetNewPosition().z + ev->GetFloat( 1 ) ) );
}
void ScriptSlave::MoveDown( Event *ev )
{
commandswaiting = true;
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y, GetNewPosition().z - ev->GetFloat( 1 ) ) );
}
void ScriptSlave::MoveNorth( Event *ev )
{
commandswaiting = true;
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y + ev->GetFloat( 1 ), GetNewPosition().z ) );
}
void ScriptSlave::MoveSouth( Event *ev )
{
commandswaiting = true;
SetNewPosition( Vector( GetNewPosition().x, GetNewPosition().y - ev->GetFloat( 1 ), GetNewPosition().z ) );
}
void ScriptSlave::MoveEast( Event *ev )
{
commandswaiting = true;
SetNewPosition( Vector( GetNewPosition().x + ev->GetFloat( 1 ), GetNewPosition().y, GetNewPosition().z ) );
}
void ScriptSlave::MoveWest( Event *ev )
{
commandswaiting = true;
SetNewPosition( Vector( GetNewPosition().x - ev->GetFloat( 1 ), GetNewPosition().y, GetNewPosition().z ) );
}
void ScriptSlave::MoveForward( Event *ev )
{
Vector v;
Vector t;
commandswaiting = true;
t = GetNewAngles() + ForwardDir;
t.AngleVectors( &v, NULL, NULL );
SetNewPosition( GetNewPosition() + v * ev->GetFloat( 1 ) );
}
void ScriptSlave::MoveBackward( Event *ev )
{
Vector v;
Vector t;
commandswaiting = true;
t = GetNewAngles() + ForwardDir;
t.AngleVectors( &v, NULL, NULL );
SetNewPosition( GetNewPosition() - v * ev->GetFloat( 1 ) );
}
void ScriptSlave::MoveLeft( Event *ev )
{
Vector v;
Vector t;
commandswaiting = true;
t = GetNewAngles() + ForwardDir;
t.AngleVectors( NULL, &v, NULL );
SetNewPosition( GetNewPosition() + v * ev->GetFloat( 1 ) );
}
void ScriptSlave::MoveRight( Event *ev )
{
Vector t;
Vector v;
commandswaiting = true;
t = GetNewAngles() + ForwardDir;
t.AngleVectors( NULL, &v, NULL );
SetNewPosition( GetNewPosition() - v * ev->GetFloat( 1 ) );
}
// exact rotate commands
void ScriptSlave::RotateXdownto( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 0 ] = ev->GetFloat( 1 );
if ( newAngles[ 0 ] < localangles[ 0 ] )
{
newAngles[ 0 ] -= 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateYdownto( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 1 ] = ev->GetFloat( 1 );
if ( newAngles[ 1 ] < localangles[ 1 ] )
{
newAngles[ 1 ] -= 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateZdownto( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 2 ] = ev->GetFloat( 1 );
if ( newAngles[ 2 ] < localangles[ 2 ] )
{
newAngles[ 2 ] -= 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateAxisdownto( Event *ev )
{
int axis;
commandswaiting = true;
axis = ev->GetInteger( 1 );
Vector newAngles( GetNewAngles() );
newAngles[ axis ] = ev->GetFloat( 1 );
if ( newAngles[ axis ] < localangles[ axis ] )
{
newAngles[ axis ] -= 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateXupto( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 0 ] = ev->GetFloat( 1 );
if ( newAngles[ 0 ] < localangles[ 0 ] )
{
newAngles[ 0 ] += 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateYupto( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 1 ] = ev->GetFloat( 1 );
if ( newAngles[ 1 ] < localangles[ 1 ] )
{
newAngles[ 1 ] += 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateZupto( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 2 ] = ev->GetFloat( 1 );
if ( newAngles[ 2 ] < localangles[ 2 ] )
{
newAngles[ 2 ] += 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::RotateAxisupto( Event *ev )
{
int axis;
commandswaiting = true;
axis = ev->GetInteger( 1 );
Vector newAngles( GetNewAngles() );
newAngles[ axis ] = ev->GetFloat( 1 );
if ( newAngles[ axis ] < localangles[ axis ] )
{
newAngles[ axis ] += 360.0f;
}
SetNewAngles( newAngles );
}
// full vector rotation
void ScriptSlave::Rotatedownto( Event *ev )
{
Vector ang;
commandswaiting = true;
ang = ev->GetVector( 1 );
Vector newAngles( GetNewAngles() );
newAngles[ 0 ] = ang[ 0 ];
if ( newAngles[ 0 ] > localangles[ 0 ] )
{
newAngles[ 0 ] -= 360.0f;
}
newAngles[ 1 ] = ang[ 1 ];
if ( newAngles[ 1 ] > localangles[ 1 ] )
{
newAngles[ 1 ] -= 360.0f;
}
newAngles[ 2 ] = ang[ 2 ];
if ( newAngles[ 2 ] > localangles[ 2 ] )
{
newAngles[ 2 ] -= 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::Rotateupto( Event *ev )
{
Vector ang;
commandswaiting = true;
ang = ev->GetVector( 1 );
Vector newAngles( GetNewAngles() );
newAngles[ 0 ] = ang[ 0 ];
if ( newAngles[ 0 ] < localangles[ 0 ] )
{
newAngles[ 0 ] += 360.0f;
}
newAngles[ 1 ] = ang[ 1 ];
if ( newAngles[ 1 ] < localangles[ 1 ] )
{
newAngles[ 1 ] += 360.0f;
}
newAngles[ 2 ] = ang[ 2 ];
if ( newAngles[ 2 ] < localangles[ 2 ] )
{
newAngles[ 2 ] += 360.0f;
}
SetNewAngles( newAngles );
}
void ScriptSlave::Rotateto( Event *ev )
{
commandswaiting = true;
Vector ang = ev->GetVector( 1 );
SetNewAngles( ang );
}
// Relative rotate commands
void ScriptSlave::RotateXdown( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 0 ] = localangles[ 0 ] - ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateYdown( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 1 ] = localangles[ 1 ] - ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateZdown( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 2 ] = localangles[ 2 ] - ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateAxisdown( Event *ev )
{
int axis;
commandswaiting = true;
axis = ev->GetInteger( 1 );
Vector newAngles( GetNewAngles() );
newAngles[ axis ] = localangles[ axis ] - ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateXup( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 0 ] = localangles[ 0 ] + ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateYup( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 1 ] = localangles[ 1 ] + ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateZup( Event *ev )
{
commandswaiting = true;
Vector newAngles( GetNewAngles() );
newAngles[ 2 ] = localangles[ 2 ] + ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateAxisup( Event *ev )
{
int axis;
commandswaiting = true;
axis = ev->GetInteger( 1 );
Vector newAngles( GetNewAngles() );
newAngles[ axis ] = localangles[ axis ] + ev->GetFloat( 1 );
SetNewAngles( newAngles );
}
void ScriptSlave::RotateX( Event *ev )
{
avelocity[ 0 ] = ev->GetFloat( 1 );
}
void ScriptSlave::RotateY( Event *ev )
{
avelocity[ 1 ] = ev->GetFloat( 1 );
}
void ScriptSlave::RotateZ( Event *ev )
{
avelocity[ 2 ] = ev->GetFloat( 1 );
}
void ScriptSlave::RotateAxis( Event *ev )
{
int axis;
axis = ev->GetInteger( 1 );
avelocity[ axis ] = ev->GetFloat( 2 );
}
void ScriptSlave::OnTouch( Event *ev )
{
const char *jumpto;
touchlabel = "";
jumpto = ev->GetString( 1 );
touchthread = ev->GetThread();
assert( jumpto && touchthread );
if ( touchthread && !touchthread->labelExists( jumpto ) )
{
ev->Error( "Label '%s' not found", jumpto );
return;
}
// if it isn't solid than we need to change it to a trigger
if ( getSolidType() == SOLID_NOT )
{
setSolidType( SOLID_TRIGGER );
}
touchlabel = jumpto;
}
void ScriptSlave::NoTouch( Event *ev )
{
touchlabel = "";
// if it is a trigger than it wasn't solid, so restore that condition
if ( getSolidType() == SOLID_TRIGGER )
{
setSolidType( SOLID_NOT );
}
}
void ScriptSlave::TouchFunc( Event *ev )
{
Event *e;
Entity *other;
if ( touchlabel.length() )
{
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
// so we should just clear our label and continue
if ( !touchthread )
{
touchlabel = "";
return;
}
other = ev->GetEntity( 1 );
setActivatingEntity( other );
e = new Event( EV_ScriptThread_Callback );
e->AddEntity( this );
e->AddString( touchlabel );
e->AddEntity( other );
touchthread->ProcessEvent( e );
}
}
void ScriptSlave::OnBlock( Event *ev )
{
const char *jumpto;
blocklabel = "";
jumpto = ev->GetString( 1 );
blockthread = ev->GetThread();
assert( jumpto && blockthread );
if ( blockthread && !blockthread->labelExists( jumpto ) )
{
ev->Error( "Label '%s' not found", jumpto );
return;
}
blocklabel = jumpto;
}
void ScriptSlave::NoBlock( Event *ev )
{
blocklabel = "";
}
void ScriptSlave::BlockFunc( Event *ev )
{
Event *e;
Entity *other;
other = ev->GetEntity( 1 );
if ( level.time >= attack_finished )
{
attack_finished = level.time + ( float )0.5;
if ( dmg != 0 )
{
other->Damage( this, this, dmg, origin, vec_zero, vec_zero, 0, 0, dmg_means_of_death );
}
}
if ( blocklabel.length() )
{
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
// so we should just clear our label and continue
if ( !blockthread )
{
blocklabel = "";
return;
}
setActivatingEntity( other );
e = new Event( EV_ScriptThread_Callback );
e->AddEntity( this );
e->AddString( blocklabel );
e->AddEntity( other );
blockthread->ProcessEvent( e );
}
}
void ScriptSlave::OnTrigger( Event *ev )
{
const char *jumpto;
triggerlabel = "";
jumpto = ev->GetString( 1 );
triggerthread = ev->GetThread();
assert( jumpto && triggerthread );
if ( triggerthread && !triggerthread->labelExists( jumpto ) )
{
ev->Error( "Label '%s' not found", jumpto );
return;
}
triggerlabel = jumpto;
}
void ScriptSlave::NoTrigger( Event *ev )
{
triggerlabel = "";
}
void ScriptSlave::TriggerFunc( Event *ev )
{
Event *e;
Entity *other;
if ( triggerlabel.length() )
{
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
// so we should just clear our label and continue
if ( !triggerthread )
{
triggerlabel = "";
return;
}
other = ev->GetEntity( 1 );
setActivatingEntity( other );
e = new Event( EV_ScriptThread_Callback );
e->AddEntity( this );
e->AddString( triggerlabel );
e->AddEntity( other );
triggerthread->ProcessEvent( e );
}
}
void ScriptSlave::OnUse( Event *ev )
{
const char *jumpto;
uselabel = "";
jumpto = ev->GetString( 1 );
usethread = ev->GetThread();
assert( jumpto && usethread );
if ( usethread && !usethread->labelExists( jumpto ) )
{
ev->Error( "Label '%s' not found", jumpto );
return;
}
uselabel = jumpto;
}
void ScriptSlave::NoUse( Event *ev )
{
uselabel = "";
}
void ScriptSlave::UseFunc( Event *ev )
{
Event *e;
Entity *other;
other = ev->GetEntity( 1 );
// See if object == key
if ( other->isSubclassOf( Equipment ) )
{
Equipment *equipment = (Equipment *)other;
if ( equipment->getTypeName() != key )
return;
}
else if ( key.length() )
{
if ( !other->isSubclassOf( Sentient ) || !( ( (Sentient *)other )->HasItem( key.c_str() ) ) )
{
Item *item;
ClassDef *cls;
cls = getClass( key.c_str() );
if ( !cls )
{
gi.WDPrintf( "No item named '%s'\n", key.c_str() );
return;
}
item = ( Item * )cls->newInstance();
item->CancelEventsOfType( EV_Item_DropToFloor );
item->CancelEventsOfType( EV_Remove );
item->ProcessPendingEvents();
gi.centerprintf ( other->edict, CENTERPRINT_IMPORTANCE_NORMAL, "$$ItemNeeded$$%s", item->getName().c_str() );
delete item;
return;
}
else if ( other->isSubclassOf( Sentient ) )
{
Item *item = ( (Sentient *)other )->FindItem( key.c_str() );
if ( !item )
return;
if ( item->isSubclassOf( Equipment ) )
{
if ( _nextNeedToUseTime < level.time )
{
gi.centerprintf ( other->edict, CENTERPRINT_IMPORTANCE_NORMAL, "$$NeedToUse$$ %s", key.c_str() );
if ( other->isSubclassOf( Player ) )
{
Player *player = (Player *)other;
player->loadUseItem( key );
}
_nextNeedToUseTime = level.time + 1.0f;
}
return;
}
}
}
if ( uselabel.length() )
{
//ScriptVariableList *vars;
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
// so we should just clear our label and continue
if ( !usethread )
{
uselabel = "";
return;
}
setActivatingEntity( other );
e = new Event( EV_ScriptThread_Callback );
e->AddEntity( this );
e->AddString( uselabel );
e->AddEntity( other );
/* vars = usethread->Vars();
vars->SetVariable( "other", other );
if ( key.length() )
{
vars->SetVariable( "key", key.c_str() );
} */
usethread->ProcessEvent( e );
}
}
void ScriptSlave::OnDamage( Event *ev )
{
const char *jumpto;
damagelabel = "";
jumpto = ev->GetString( 1 );
damagethread = ev->GetThread();
assert( jumpto && damagethread );
if ( damagethread && !damagethread->labelExists( jumpto ) )
{
ev->Error( "Label '%s' not found", jumpto );
return;
}
damagelabel = jumpto;
}
void ScriptSlave::NoDamage( Event *ev )
{
damagelabel = "";
}
void ScriptSlave::DamageFunc( Event *ev )
{
Event *e;
//Entity *inflictor;
Entity *attacker;
//int damage;
//Vector position;
//Vector direction;
//ScriptVariableList *vars;
attacker = ev->GetEntity( 3 );
if ( !_canBeAttackedByOtherScriptSlaves )
{
if ( attacker->isSubclassOf(ScriptSlave) )
return;
}
if ( _handlesDamage )
{
Event *newDamageEvent = new Event (ev);
Entity::DamageEvent(newDamageEvent);
}
if ( damagelabel.length() )
{
// since we use a SafePtr, the thread pointer will be NULL if the thread has ended
// so we should just clear our label and continue
if ( !damagethread )
{
damagelabel = "";
return;
}
if( _requiredMODlist.NumObjects() != 0 )
{
bool modMatches = false;
for( int i = 1; !modMatches && i <= _requiredMODlist.NumObjects(); i++ )
{
str& modname = _requiredMODlist.ObjectAt( i );
int modID = MOD_NameToNum( modname );
int damageMOD = ev->GetInteger( 9 );
if ( modID == damageMOD )
modMatches = true;
}
if( !modMatches )
return;
}
setActivatingEntity( attacker );
e = new Event( EV_ScriptThread_Callback );
e->AddEntity( this );
e->AddString( damagelabel );
e->AddEntity( attacker );
/* damage = ev->GetInteger( 1 );
inflictor = ev->GetEntity( 2 );
position = ev->GetVector( 4 );
direction = ev->GetVector( 5 ); */
/* vars = damagethread->Vars();
vars->SetVariable( "damage", damage );
vars->SetVariable( "inflictor", inflictor );
vars->SetVariable( "attacker", attacker );
vars->SetVariable( "position", position );
vars->SetVariable( "direction", direction ); */
damagethread->ProcessEvent( e );
}
if ( _bloodModel.length() )
{
SpawnEffect( _bloodModel , ev->GetVector( 4 ) , ev->GetVector( 6 ) , 1.0f );
}
if ( _damageEffect.length() )
{
//SpawnEffect( "models/fx/fx-impactburn-sniperrifle.tik", ev->GetVector( 4 ), ev->GetVector( 6 ), 1.0f );
SpawnEffect( "models/fx/fx-electricitymesh-impactpoint.tik", ev->GetVector( 4 ), ev->GetVector( 6 ), 1.0f );
}
}
void ScriptSlave::SetDamage( Event *ev )
{
dmg = ev->GetFloat( 1 );
}
void ScriptSlave::SetMeansOfDeath( Event *ev )
{
dmg_means_of_death = MOD_NameToNum( ev->GetString( 1 ) );
}
void ScriptSlave::CreatePath( SplinePath *path, splinetype_t type )
{
SplinePath* node;
SplinePath* nextNode;
if ( !splinePath )
{
splinePath = new BSpline;
}
splinePath->Clear();
splinePath->SetType( type );
node = path;
while( node != NULL )
{
splinePath->AppendControlPoint( node->origin, node->angles, node->speed );
// get the next node and check it before using it
nextNode = node->GetNext();
if( nextNode == node )
{
gi.Error( ERR_DROP, "info_splinepath '%s' targets itself\n", node->targetname.c_str() );
}
// don't loop
if ( nextNode == path )
{
break;
}
// move to the next node
node = nextNode;
}
}
void ScriptSlave::FollowPath( Event *ev )
{
int i, argnum;
Entity * ent;
const char * token;
SplinePath *path;
qboolean clamp;
float starttime;
ent = ev->GetEntity( 1 );
argnum = 2;
starttime = -2;
clamp = true;
ignoreangles = false;
splineangles = true;
for ( i = argnum; i <= ev->NumArgs() ; i++ )
{
token = ev->GetString( i );
if (!strcmpi( token, "ignoreangles"))
{
ignoreangles = true;
}
else if (!strcmpi( token, "normalangles"))
{
splineangles = false;
}
else if (!strcmpi (token, "loop"))
{
clamp = false;
}
else if ( IsNumeric( token ) )
{
starttime = (float)atof( token );
}
else
{
ev->Error( "Unknown followpath command %s.", token );
}
}
if ( ent && ent->isSubclassOf( SplinePath ) )
{
commandswaiting = true;
path = ( SplinePath * )ent;
if ( clamp )
CreatePath( path, SPLINE_CLAMP );
else
CreatePath( path, SPLINE_LOOP );
currentNode = path;
if ( currentNode->thread != "" )
{
if ( !ExecuteThread( currentNode->thread , true , this) )
{
gi.Error( ERR_DROP, "Scriptslave could not start thread '%s' from info_splinepath '%s'\n",
currentNode->thread.c_str(), currentNode->targetname.c_str() );
}
}
if ( currentNode->triggertarget != "" )
{
Entity *ent;
Event *event;
ent = NULL;
do
{
ent = G_FindTarget( ent, currentNode->triggertarget.c_str() );
if ( !ent )
{
break;
}
event = new Event( EV_Activate );
event->AddEntity( this );
ent->PostEvent( event, 0.0f );
}
while ( 1 );
}
splineTime = starttime;
lastTime = (int)(splineTime + 2.0f);
newTime = (int)(splineTime + 2.0f);
CancelEventsOfType( EV_ScriptSlave_FollowingPath );
if ( !ignoreangles )
{
avelocity = vec_zero;
}
velocity = vec_zero;
}
}
void ScriptSlave::EndPath( Event *ev )
{
if ( !splinePath )
return;
delete splinePath;
splinePath = NULL;
velocity = vec_zero;
if ( !ignoreangles )
{
avelocity = vec_zero;
}
}
void ScriptSlave::FollowingPath( Event *ev )
{
Vector pos;
Vector orient;
float speed_multiplier;
if ( !splinePath )
return;
if ( !thinking )
{
velocity = vec_zero;
if ( !ignoreangles )
{
avelocity = vec_zero;
}
return;
//PostEvent( EV_ScriptSlave_FollowingPath, level.frametime );
}
if ( ( splinePath->GetType() == SPLINE_CLAMP ) && ( splineTime > ( splinePath->EndPoint() - 2.0f ) ) )
{
delete splinePath;
splinePath = NULL;
velocity = vec_zero;
if ( !ignoreangles )
{
avelocity = vec_zero;
}
moving = false;
ProcessEvent( EV_ScriptSlave_MoveDone );
return;
}
if ( ( lastTime != newTime ) && currentNode )
{
if ( newTime > 1 )
{
if ( currentNode->thread != "" )
{
if ( !ExecuteThread( currentNode->thread ,true , this) )
{
gi.Error( ERR_DROP, "Scriptslave could not start thread '%s' from info_splinepath '%s'\n",
currentNode->thread.c_str(), currentNode->targetname.c_str() );
}
}
if ( currentNode->triggertarget != "" )
{
Entity *ent;
Event *event;
ent = NULL;
do
{
ent = G_FindTarget( ent, currentNode->triggertarget.c_str() );
if ( !ent )
{
break;
}
event = new Event( EV_Activate );
event->AddEntity( this );
ent->PostEvent( event, 0.0f );
}
while ( 1 );
}
}
currentNode = currentNode->GetNext();
}
lastTime = newTime;
speed_multiplier = splinePath->Eval( splineTime, pos, orient );
splineTime += level.frametime * speed_multiplier;
velocity = ( pos - origin ) * ( 1.0f / level.frametime );
if ( !ignoreangles )
{
if ( splineangles )
{
avelocity = ( orient - angles ) * ( 1.0f / level.frametime );
}
else
{
float len;
len = velocity.length();
if ( len > 0.05f )
{
Vector ang;
Vector dir;
float aroll;
aroll = avelocity[ ROLL ];
dir = velocity * ( 1.0f / len );
ang = dir.toAngles();
avelocity = ( ang - angles ) * ( 1.0f / level.frametime );
avelocity[ ROLL ] = aroll;
}
else
avelocity = vec_zero;
}
}
newTime = splineTime + 2.0f;
if ( newTime < 0 )
{
newTime = 0;
}
PostEvent( EV_ScriptSlave_FollowingPath, level.frametime );
}
void ScriptSlave::Explode( Event *ev )
{
float damage;
if ( ev->NumArgs() )
{
damage = ev->GetFloat( 1 );
}
else
{
damage = 120.0f;
}
CreateExplosion( origin, damage, this, this, this );
}
void ScriptSlave::NotShootable( Event *ev )
{
setContents( 0 );
}
void ScriptSlave::OpenPortal( Event *ev )
{
if ( !_portalOpen )
{
gi.AdjustAreaPortalState( this->edict, true );
_portalOpen = true;
}
}
void ScriptSlave::ClosePortal( Event *ev )
{
if ( _portalOpen )
{
gi.AdjustAreaPortalState( this->edict, false );
_portalOpen = false;
}
}
void ScriptSlave::PhysicsOn( Event *ev )
{
commandswaiting = false;
setMoveType( MOVETYPE_BOUNCE );
setSolidType( SOLID_BBOX );
velocity = Vector(0, 0, 1);
edict->clipmask = MASK_SOLID|CONTENTS_BODY;
}
void ScriptSlave::PhysicsOff( Event *ev )
{
Event * event;
commandswaiting = false;
setMoveType( MOVETYPE_PUSH );
edict->clipmask = 0;
// become solid again
event = new Event( EV_Model );
event->AddString( model );
PostEvent( event, 0.0f );
}
void ScriptSlave::PhysicsVelocity( Event *ev )
{
velocity += ev->GetVector( 1 );
}
void ScriptSlave::StopEvent( Event *ev )
{
Stop();
}
void ScriptSlave::Stop( void )
{
thinking = false;
}
void ScriptSlave::ContinueEvent( Event *ev )
{
Continue();
}
void ScriptSlave::Continue( void )
{
thinking = true;
PostEvent( EV_ScriptSlave_FollowingPath, level.frametime );
}
//-----------------------------------------------------
//
// Name: Think
// Class: ScriptSlave
//
// Description: Processes the updates for the Script Slave.
//
// Parameters: None
//
// Returns: None
//-----------------------------------------------------
void ScriptSlave::Think()
{
if(flags & FL_TOUCH_TRIGGERS)
{
G_TouchTriggers(this);
}
}
/*****************************************************************************/
/*QUAKED script_model (0 0.5 1) (0 0 0) (0 0 0) NOT_SOLID LIT_STATIC
******************************************************************************/
Event EV_ScriptModel_SetAnim
(
"anim",
EV_DEFAULT,
"s",
"anim_name",
"Sets the script model's animation"
);
Event EV_ScriptModel_SetAnimDriven
(
"animdriven",
EV_DEFAULT,
"B",
"boolean",
"Sets the script model to be anim driven"
);
Event EV_ScriptModel_AnimOnce
(
"animonce",
EV_SCRIPTONLY,
"s",
"anim_name",
"Sets the script model's animation but only plays it once"
);
CLASS_DECLARATION( ScriptSlave, ScriptModel, "script_model" )
{
{ &EV_Gib, &ScriptModel::GibEvent },
{ &EV_SetAngle, &ScriptModel::SetAngleEvent },
{ &EV_ScriptModel_SetAnim, &ScriptModel::SetAnimEvent },
{ &EV_ScriptModel_SetAnimDriven, &ScriptModel::SetAnimDrivenEvent },
{ &EV_ScriptModel_AnimOnce, &ScriptModel::AnimOnceEvent },
{ &EV_Model, &ScriptModel::SetModelEvent },
{ NULL, NULL },
};
ScriptModel::ScriptModel()
{
// this is a tiki model
edict->s.eType = ET_MODELANIM;
animationDriven = false;
animate = new Animate( this );
}
void ScriptModel::Think( void )
{
total_delta = vec_zero;
ScriptSlave::Think();
if(animationDriven)
{
localangles = InterceptTargetXY( GetNewPosition(), Vector::Identity(), velocity.lengthXY() );
SetNewAngles( localangles );
setAngles( localangles );
// Set velocity based on current delta move
Vector forward;
Vector left;
Vector up;
localangles.AngleVectors( &forward, &left, &up );
total_delta /= level.frametime;
velocity = ( forward * total_delta[0] ) + ( left * total_delta[1] ) + ( up * total_delta[2] );
}
}
void ScriptModel::SetModelEvent( Event *ev )
{
char modelname[256] ;
char *tmpPtr ;
strcpy(modelname, ev->GetString( 1 ) );
tmpPtr = strstr(modelname, "*");
if (tmpPtr)
{
ev->SetString( 1 , tmpPtr );
}
ScriptSlave::SetModelEvent( ev );
setSolidType( SOLID_BBOX );
if ( ( gi.IsModel( edict->s.modelindex ) ) && !mins.length() && !maxs.length() )
{
gi.CalculateBounds( edict->s.modelindex, edict->s.scale, mins, maxs );
}
}
void ScriptModel::SetAnimEvent( Event *ev )
{
const char * const animname = ev->GetString( 1 );
if ( animname && strlen( animname ) && gi.IsModel( edict->s.modelindex ) )
{
int animnum = gi.Anim_NumForName( edict->s.modelindex, animname );
if ( animnum >= 0 )
{
animate->NewAnim( animnum );
}
}
}
void ScriptModel::SetAnimDrivenEvent( Event *ev )
{
if ( (ev->NumArgs() > 0) && ( ev->GetBoolean( 1 ) == false ) )
{
animationDriven = false;
}
else
{
animationDriven = true;
turnThinkOn();
}
}
void ScriptModel::AnimOnceEvent( Event *ev )
{
const char * animname;
animname = ev->GetString( 1 );
if ( animname && strlen( animname ) && gi.IsModel( edict->s.modelindex ) )
{
animate->RandomAnimate( animname, EV_StopAnimating );
}
}
void ScriptModel::SetAngleEvent( Event *ev )
{
float angle;
angle = ev->GetFloat( 1 );
if ( angle == -1.0f )
{
ForwardDir = Vector( 0.0f, 0.0f, 90.0f );
localangles = Vector( -90.0f, 0.0f, 0.0f );
}
else if ( angle == -2.0f )
{
ForwardDir = Vector( 0.0f, 0.0f, -90.0f );
localangles = Vector( 90.0f, 0.0f, 0.0f );
}
else
{
ForwardDir = Vector( 0.0f, angle, 0.0f );
localangles = Vector( 0.0f, angle, 0.0f );
}
setAngles( localangles );
}
void ScriptModel::GibEvent( Event *ev )
{
int num,power;
float scale;
setSolidType( SOLID_NOT );
hideModel();
if ( !com_blood->integer )
{
PostEvent( EV_Remove, 0.0f );
return;
}
num = ev->GetInteger( 1 );
power = ev->GetInteger( 2 );
scale = ev->GetFloat( 3 );
power = -power;
if ( ev->NumArgs() > 3 )
{
CreateGibs( this, power, scale, num, ev->GetString( 4 ) );
}
else
{
CreateGibs( this, power, scale, num );
}
PostEvent( EV_Remove, 0.0f );
}
/*****************************************************************************/
/*QUAKED script_origin (1.0 0 0) (-8 -8 -8) (8 8 8)
Used as an alternate origin for objects. Bind the object to the script_origin
in order to simulate changing that object's origin.
******************************************************************************/
CLASS_DECLARATION( ScriptSlave, ScriptOrigin, "script_origin" )
{
{ &EV_Model, &ScriptOrigin::SetModelEvent },
{ NULL, NULL }
};
ScriptOrigin::ScriptOrigin()
{
setContents( 0 );
setSolidType( SOLID_NOT );
}
/*****************************************************************************/
/*QUAKED script_skyorigin (1.0 0 0) ?
Used to specify the origin of a portal sky
******************************************************************************/
Event EV_ScriptSkyOrigin_SetBasePosition
(
"baseposition",
EV_SCRIPTONLY,
"v",
"base_position",
"Sets the base position of the sky origin."
);
Event EV_ScriptSkyOrigin_SetPlayerBasePosition
(
"playerbaseposition",
EV_SCRIPTONLY,
"v",
"base_position",
"Sets the base position for the player for the sky origin."
);
Event EV_ScriptSkyOrigin_SetTranslationMultiplier
(
"translationmult",
EV_SCRIPTONLY,
"f",
"translation_multiplier",
"Sets the translation multiplier for the sky origin."
);
Event EV_ScriptSkyOrigin_SetMaxDistance
(
"maxtranslationdist",
EV_SCRIPTONLY,
"f",
"max_translation_distance",
"Sets the maximum distance the sky origin will translate."
);
CLASS_DECLARATION( ScriptSlave, ScriptSkyOrigin, "script_skyorigin" )
{
{ &EV_ScriptSkyOrigin_SetBasePosition, &ScriptSkyOrigin::SetBasePosition },
{ &EV_ScriptSkyOrigin_SetPlayerBasePosition, &ScriptSkyOrigin::SetPlayerBasePosition },
{ &EV_ScriptSkyOrigin_SetTranslationMultiplier, &ScriptSkyOrigin::SetTranslationMultiplier },
{ &EV_ScriptSkyOrigin_SetMaxDistance, &ScriptSkyOrigin::SetMaxDistance },
{ NULL, NULL }
};
ScriptSkyOrigin::ScriptSkyOrigin()
{
edict->s.renderfx |= RF_SKYORIGIN;
setContents( 0 );
setSolidType( SOLID_NOT );
turnThinkOn();
use_base_position = false;
use_player_base_position = false;
translation_multiplier = 0;
max_distance = 0;
}
void ScriptSkyOrigin::Think( void )
{
Vector delta;
Entity *player;
Vector new_origin;
new_origin = origin;
if ( use_base_position )
{
if ( translation_multiplier )
{
// Get player
player = g_entities[ 0 ].entity;
if ( !use_player_base_position )
{
// Get current player position
player_base_position = player->origin;
use_player_base_position = true;
}
// Calculate the new origin
delta = player->origin - player_base_position;
delta *= translation_multiplier;
if ( max_distance && ( delta.length() > max_distance ) )
{
delta.normalize();
delta *= max_distance;
}
new_origin = base_position + delta;
}
else
{
new_origin = base_position;
}
}
setOrigin( new_origin );
}
void ScriptSkyOrigin::SetBasePosition( Event *ev )
{
use_base_position = true;
base_position = ev->GetVector( 1 );
use_player_base_position = false;
}
void ScriptSkyOrigin::SetPlayerBasePosition( Event *ev )
{
use_player_base_position = true;
player_base_position = ev->GetVector( 1 );
}
void ScriptSkyOrigin::SetTranslationMultiplier( Event *ev )
{
translation_multiplier = ev->GetFloat( 1 );
}
void ScriptSkyOrigin::SetMaxDistance( Event *ev )
{
max_distance = ev->GetFloat( 1 );
}
//1ST PLAYABLE HACK STUFF
void ScriptSlave::Hack_AddParms( Event *ev )
{
_forcefieldNumber = ev->GetFloat( 1 );
_triggerNumber = ev->GetFloat( 2 );
}
void ScriptSlave::Hack_GetForceFieldNumber( Event *ev )
{
ev->ReturnFloat( _forcefieldNumber );
}
void ScriptSlave::Hack_GetScanner( Event *ev )
{
ev->ReturnEntity( _scanner );
}
void ScriptSlave::Hack_GetTriggerNumber( Event *ev )
{
ev->ReturnFloat( _triggerNumber );
}
void ScriptSlave::HandlesDamage( Event *ev )
{
_handlesDamage = ev->GetBoolean( 1 );
}
void ScriptSlave::setDamageEffect( Event *ev )
{
_damageEffect = ev->GetString( 1 );
}
void ScriptSlave::setBloodModel( Event *ev )
{
_bloodModel = ev->GetString( 1 );
}
void ScriptSlave::addRequiredDamageMOD( Event *ev )
{
str modname( ev->GetString( 1 ) );
assert( modname.length() > 0 );
_requiredMODlist.AddObject( modname );
}
void ScriptSlave::setCanBeAttackedByOtherSlaves(Event *ev)
{
_canBeAttackedByOtherScriptSlaves = ev->GetBoolean( 1 );
}