コード例 #1
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
// Alert-Stuff... I don't know. I feel like removing this and stick to the entity spawning and setup.
// game.AlertSetup(entity ent, string greentarget, string yellowtarget, string redtarget, string bluetarget,
//					string greensound, string yellowsound, string redsound, string bluesound, integer mode)
static int Game_AlertSetup(lua_State *L) {

	LUA_DEBUG("BEGIN - game.AlertSetup");

	if(luaAlertState != NULL) {
		LUA_DEBUG("ERROR - game.AlertSetup - luaArlterState != NULL");
		lua_pushboolean(L, 0);
		return 1;
	}

	luaAlertState = (luaAlertState_t *)malloc(sizeof(luaAlertState_t));
	if(luaAlertState == NULL) {
		LUA_DEBUG("ERROR - game.AlertSetup - luaAlertState NULL");
		lua_pushboolean(L, 0);
		return 1;
	}

	luaAlertState->targets[0] = (char *)luaL_checkstring(L, 1);
	luaAlertState->targets[1] = (char *)luaL_checkstring(L, 2);
	luaAlertState->targets[2] = (char *)luaL_checkstring(L, 3);
	luaAlertState->targets[3] = (char *)luaL_checkstring(L, 4);

	luaAlertState->sounds[0] = (char *)luaL_checkstring(L, 5);
	luaAlertState->sounds[1] = (char *)luaL_checkstring(L, 6);
	luaAlertState->sounds[2] = (char *)luaL_checkstring(L, 7);
	luaAlertState->sounds[3] = (char *)luaL_checkstring(L, 8);

	luaAlertState->mode = luaL_checkint(L, 9);

	luaAlertState->cond = 0;

	LUA_DEBUG("END - game.AlertSetup");
	lua_pushboolean(L, 1);
	return 1;
}
コード例 #2
0
ファイル: lua_mover.c プロジェクト: gitter-badger/rpgxEF
/***
Moves ent with a given speed to the specified values. Can also be stowed in a vector pos.
@function ToPosition
@param ent Entity or entity number.
@param speed Speed to move with.
@param x X coordinates.
@param y Y coordinates.
@param z Z coordinates.
@return Success or failure.
*/
static int Mover_ToPosition(lua_State * L)
{
	vec3_t          newOrigin;
	lent_t			*lent;
	gentity_t      *ent = NULL;
	float           speed;
	vec_t          *target;
	int				id = 0;

	if(lua_isnumber(L, 1)) {
		id = luaL_checkint(L, 1);
		if(id < 0 ||id > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = &g_entities[id];
		if(ent == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		lent = Lua_GetEntity(L,1);
		if(lent == NULL || lent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = lent->e;
	}

	speed = (float)luaL_checknumber(L, 2);

	if(Lua_IsVector(L, 3))
	{
		target = Lua_GetVector(L, 3);
		VectorCopy(target, newOrigin);
	}
	else
	{
		newOrigin[0] = luaL_checkint(L, 3);
		newOrigin[1] = luaL_checkint(L, 4);
		newOrigin[2] = luaL_checkint(L, 5);
	}
	

	LUA_DEBUG("Mover_ToPosition - start: ent=%d pos=%s speed=%f", ent->s.number, vtos(newOrigin), speed);
	if(ent)
	{
		BG_EvaluateTrajectory(&ent->s.pos, level.time, ent->s.pos.trBase);
		SetTrajectoryLinear(&ent->s.pos, speed, newOrigin);
		ent->moverState = MOVER_LUA;
		trap_LinkEntity(ent);
		LUA_DEBUG("Mover_ToPosition - return: moving");
	}
	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #3
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Get the current level time in milliseconds. Level time is the time since level start.
@function LevelTime
@return Level time in milliseconds.
*/
static int Game_Leveltime(lua_State * L)
{
	LUA_DEBUG("BEGIN - game.Leveltime");

	lua_pushinteger(L, level.time);

	LUA_DEBUG("INFO - game.Leveltime - start/return: leveltime=%d", level.time);
	LUA_DEBUG("BEGIN - game.Leveltime");
	return 1;
}
コード例 #4
0
ファイル: lua_mover.c プロジェクト: gitter-badger/rpgxEF
/***
Set the position of ent to the specified value.
@function SetPosition
@param ent Entity or entity number.
@param vec Vector containing the new position.
@return Success or failure.
*/
static int Mover_SetPosition(lua_State * L)
{
	vec3_t          newOrigin;
	lent_t			*lent;
	gentity_t      *ent = NULL;
	vec_t          *target;
	int				id = 0;

	if(lua_isnumber(L, 1)) {
		id = luaL_checkint(L, 1);
		if(id < 0 || id > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = &g_entities[id];
		if(ent == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		lent = Lua_GetEntity(L, 1);
		if(lent == NULL || lent->e == NULL)
		{
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = lent->e;
	}

	if(Lua_IsVector(L, 2))
	{
		target = Lua_GetVector(L, 2);
		VectorCopy(target, newOrigin);
	}
	else
	{
		newOrigin[0] = luaL_checkint(L, 2);
		newOrigin[1] = luaL_checkint(L, 3);
		newOrigin[2] = luaL_checkint(L, 4);
	}
	LUA_DEBUG("Mover_SetPosition - start: ent=%d pos=%s", ent->s.number, vtos(newOrigin));
	if(ent)
	{
		G_SetOrigin(ent, newOrigin);
		trap_LinkEntity(ent);
		LUA_DEBUG("Mover_SetPosition - return: moved");
	}
	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #5
0
ファイル: lua_misc.cpp プロジェクト: dbt1/neutrino-mp
int CLuaInstMisc::strSub(lua_State *L)
{
	/* workaround for deprecated functions */
	CLuaMisc *D;
	if (luaL_testudata(L, 1, LUA_CLASSNAME) == NULL) {
		D = MiscCheckData(L, 1);
		if (!D) return 0;
	}
	/* CLuaMisc *D = MiscCheckData(L, 1);
	if (!D) return 0; */
	int numargs = lua_gettop(L);
	if (numargs < 3) {
		printf("CLuaInstMisc::%s: not enough arguments (%d, expected 2 (or 3))\n", __func__, numargs);
		lua_pushstring(L, "");
		return 1;
	}
	const char *s1;
	size_t pos=0, len=std::string::npos;
	std::string ret="";
	s1 = luaL_checkstring(L, 2);
	pos = luaL_checkint(L, 3);
	if (numargs > 3)
		len = (size_t)luaL_checkint(L, 4);

	std::string str(s1);
	ret = str.substr(pos, len);

	LUA_DEBUG("####[%s:%d] str_len: %d, pos: %d, len: %d, ret_len: %d\n", __func__, __LINE__, str.length(), pos, len, ret.length());
	lua_pushstring(L, ret.c_str());
	return 1;
}
コード例 #6
0
ファイル: lua_trace.c プロジェクト: gitter-badger/rpgxEF
/***
Does a trace.
@function DoTrace
@param start start-point of the trace.
@param mins minimal distance of trace (nil if unused)
@param maxs maximal distance of trace (nil if unused)
@param end end-point of trace
@param passEnt Number of ents to pass
@param contents Set content flags.
*/
static int Trace_DoTrace(lua_State *L) {
	trace_t *tr;
	vec_t *start, *end, *mins = NULL, *maxs = NULL;
	int passEnt, contents;

	start = Lua_GetVector(L, 1);
	if(!lua_isnil(L, 2))
		mins = Lua_GetVector(L, 2);
	if(!lua_isnil(L, 3))
		maxs = Lua_GetVector(L, 3);
	end = Lua_GetVector(L, 4);
	passEnt = (int)luaL_checknumber(L, 5);
	contents = (int) luaL_checknumber(L, 6);

	tr = (trace_t *)malloc(sizeof(trace_t));
	if(!tr) {
		LUA_DEBUG("Trace_DoTrace - was unable to allocate a trace_t.\n");
		lua_pushnil(L);
		return 1;
	}

	trap_Trace(tr, start, mins, maxs, end, passEnt, contents);

	Lua_PushTrace(L, tr);

	return 1;
}
コード例 #7
0
ファイル: lua_cc_text.cpp プロジェクト: dbt1/neutrino-mp
int CLuaInstCCText::CCTextDelete(lua_State *L)
{
	LUA_DEBUG("CLuaInstCCText::%s %d\n", __func__, lua_gettop(L));
	CLuaCCText *D = CCTextCheck(L, 1);
	if (!D) return 0;
	delete D;
	return 0;
}
コード例 #8
0
int CLuaInstProgressWindow::CProgressWindowDelete(lua_State *L)
{
	LUA_DEBUG("CLuaInstProgressWindow::%s %d\n", __func__, lua_gettop(L));
	CLuaCProgressWindow *D = CProgressWindowCheck(L, 1);
	if (!D) return 0;
	delete D;
	return 0;
}
コード例 #9
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Returns the value of the global variable name. Returns nil if the variable does not exist.
@function GetGlobal
@param name Name of Global variable.
@return value of Global variable.
*/
static int Game_GetGlobal(lua_State *L) {
	char *name;

	LUA_DEBUG("BEGIN - game.SetGlobal");

	name = (char *)luaL_checkstring(L, 1);

	if(name == NULL) {
		LUA_DEBUG("ERROR - game.SetGlobal - name NULL");
		lua_pushnil(L);
		return 0;
	}

	lua_getglobal(L, name);
	LUA_DEBUG("END - game.SetGlobal");
	return 1;
}
コード例 #10
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
static int Game_AlertAddShader(lua_State *L) {
	int cond;
	char *shader;

	LUA_DEBUG("BEGIN - game.AlertAddShader");

	if(luaAlertState == NULL) {
		LUA_DEBUG("ERROR - game.AlertAddShader - luaAlertShader NULL");
		lua_pushboolean(L, 0);
		return 1;
	}

	cond = luaL_checkint(L, 1);
	if(cond < 0 || cond > 3) {
		LUA_DEBUG("ERROR - game.AlertAddShader - cond out of range");
		lua_pushboolean(L, 0);
		return 1;
	}

	shader = (char *)luaL_checkstring(L, 2);
	if(shader == NULL) {
		LUA_DEBUG("ERROR - game.AlertAddShader - shader NULL");
		lua_pushboolean(L, 0);
		return 1;
	}

	if((strlen(shader) + 1) > MAX_QPATH) {
		LUA_DEBUG("ERROR - game.AlertAddShader - strlen(shader)+1 > MAX_QPATH");
		lua_pushboolean(L, 0);
		return 1;
	}

	if(luaAlertState->shaders[cond] == NULL) {
		luaAlertState->shaders[cond] = (char *)malloc(sizeof(char) * (strlen(shader) + 1));
		if(luaAlertState->shaders[cond] == NULL) {
			LUA_DEBUG("ERROR - game.AlertAddShader - alloc failed");
			lua_pushboolean(L, 0);
			return 1;
		}
		strncpy(luaAlertState->shaders[cond], shader, sizeof(luaAlertState->shaders[cond]));
	} else {
		void *tmp = realloc(luaAlertState->shaders[cond], sizeof(char) * (strlen(luaAlertState->shaders[cond]) +
												strlen(shader) + 1));
		if(tmp == NULL){
			LUA_DEBUG("ERROR - game.AlertAddShader - realloc failed");
			lua_pushboolean(L, 0);
			return 1;
		}
		luaAlertState->shaders[cond] = tmp;
		Com_sprintf(luaAlertState->shaders[cond], sizeof(luaAlertState->shaders[cond]), "%s\n%s", luaAlertState->shaders[cond], shader);
	}

	lua_pushboolean(L, 1);
	LUA_DEBUG("END - game.AlertAddShader");
	return 1;
}
コード例 #11
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Prints text to the clients console that has the client number clientNum. If clientNum is -1 the text gets printed to all clients consoles.
@function ClientPrint
@param clientNum Client number.
@param text Text to print.
*/
static int Game_ClientPrint(lua_State *L) {
	int			i;
	char		buf[MAX_STRING_CHARS];
	int			n = lua_gettop(L);
	int			clNum =  luaL_checknumber(L, 1);
	gentity_t	*player;

	memset(buf, 0, sizeof(buf));

	lua_getglobal(L, "tostring");

	LUA_DEBUG("BEGIN - game.ClientPrint");

	for(i = 1; i < n; i++) {
		const char		*s;

		lua_pushvalue(L, -1);
		lua_pushvalue(L, i);
		lua_call(L, 1, 1);
		s = lua_tostring(L, 2);

		if(s == NULL)
		{
			LUA_DEBUG("BEGIN - game.ClientPrint - no string");
			lua_pushboolean(L, qfalse);
			return 1;
		}

		Q_strcat(buf, sizeof(buf), s);

		lua_pop(L, 1);
	}

	if(clNum != -1) {
		player = &g_entities[clNum];
		if(player && player->client) {
			G_PrintfClient(player, "%s", buf);
		}
	} else {
		G_PrintfClientAll("%s", buf);
	}

	LUA_DEBUG("END - game.ClientPrint");
	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #12
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Damage and player or entity.
@function Damage
@param target Target entity.
@param inflictor Inflicting entity. Can be nil.
@param attacker Attacking entity. Can be nil.
@param direction Direction of knockback. Can be nil.
@param point Point where the damage is inflicted. Can be nil.
@param damage Ammount of damage.
@param dflags Damage flags.
@param mod Means of death.
@return Success or fail.
*/
static int Game_Damage(lua_State *L) {
	lent_t *lent;
	gentity_t *targ = NULL, *inflictor = NULL, *attacker = NULL;
	vec_t *dir = NULL, *point = NULL;
	int damage = 0, dflags = 0, mod = 0;

	LUA_DEBUG("BEGIN - game.Damage");

	lent = Lua_GetEntity(L, 1);
	if(lent == NULL || lent->e == NULL) {
		LUA_DEBUG("ERROR - game.Damage - entity NULL");
		lua_pushboolean(L, qfalse);
		return 1;
	}
	targ = lent->e;
	if(!lua_isnil(L, 2)) {
		lent = Lua_GetEntity(L, 2);
		if(lent && lent->e)  {
			inflictor = lent->e;
		}
	}
	if(!lua_isnil(L, 3)) {
		lent = Lua_GetEntity(L, 3);
		if(lent && lent->e) {
			attacker = lent->e;
		}
	}
	if(!lua_isnil(L, 4)) {
		dir = Lua_GetVector(L, 4);
	}
	if(!lua_isnil(L, 5)) {
		point = Lua_GetVector(L, 5);
	}
	damage = (int)luaL_checknumber(L, 6);
	dflags = (int)luaL_checknumber(L, 7);
	mod = (int)luaL_checknumber(L, 8);

	G_Damage(targ, inflictor, attacker, dir, point, damage, dflags, mod);

	lua_pushboolean(L, qtrue);
	LUA_DEBUG("END - game.Damage");
	return 1;
}
コード例 #13
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Sets a global Lua variable which is called name to value. Creates a new global variable if a variable of name does not exist. Value can be of any type.
@function SetGlobal
@param name Name of global variable.
@param value New value for global variable.
*/
static int Game_SetGlobal(lua_State *L) {
	char *name;

	LUA_DEBUG("BEGIN - game.SetGlobal");

	name = (char *)luaL_checkstring(L, 1);

	if(name == NULL) {
		LUA_DEBUG("ERROR - game.SetGlobal - name NULL");
		lua_pushboolean(L, qfalse);
		return 0;
	}

	lua_pushvalue(L, 2);
	lua_setglobal(L, name);

	LUA_DEBUG("END - game.SetGlobal");
	lua_pushboolean(L, qtrue);
	return 0;
}
コード例 #14
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Repair an entity.
@function Repair
@param target Target entity.
@param rate Repair rate.
@return Success or fail.
*/
static int Game_Repair(lua_State *L) {
	lent_t *lent;
	float rate;

	LUA_DEBUG("BEGIN - game.Repair");

	lent = Lua_GetEntity(L, 1);
	if(lent == NULL || lent->e == NULL) {
		LUA_DEBUG("ERROR - game.Repair - entity NULL");
		lua_pushboolean(L, qfalse);
		return 1;
	}
	
	rate = (float)luaL_checknumber(L, 2);

	G_Repair(lent->e, NULL, rate); // FIXME ... trance ent?

	LUA_DEBUG("END - game.Repair");
	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #15
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Prints text to the center of the screen of the client with client number clientNum. If clientNum is -1 the text gets printed for all clients.
@function CenterPrint
@param clientNum Client number.
@param text Text to print.
*/
static int Game_CenterPrint(lua_State *L) {
	int			i;
	char		buf[MAX_STRING_CHARS];
	int			n = lua_gettop(L);
	int			clNum = luaL_checknumber(L, 1);

	memset(buf, 0, sizeof(buf));

	lua_getglobal(L, "tostring");

	LUA_DEBUG("BEGIN - game.CenterPrint");

	for(i = 1; i < n; i++)
	{
		const char     *s;

		lua_pushvalue(L, -1);
		lua_pushvalue(L, i);
		lua_call(L, 1, 1);
		s = lua_tostring(L, 2);

		if(s == NULL)
		{
			LUA_DEBUG("ERROR - game.CenterPrint - no string");
			lua_pushboolean(L, qfalse);
			return 1;
		}

		Q_strcat(buf, sizeof(buf), s);

		lua_pop(L, 1);
	}

	
	trap_SendServerCommand(clNum, va("servercprint \"" S_COLOR_WHITE "%s\n\"", buf));

	LUA_DEBUG("END - game.CenterPrint");
	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #16
0
ファイル: lua_mover.c プロジェクト: gitter-badger/rpgxEF
/***
Stops rotational movement on ent immediately.
@function HaltAngles
@param ent Entity or entity number.
@return Success or failure.
*/
static int Mover_HaltAngles(lua_State * L)
{
	lent_t			*lent;
	gentity_t       *ent = NULL;
	int				id = 0;

	if(lua_isnumber(L, 1)) {
		id = luaL_checkint(L, 1);
		if(id < 0 || id > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = &g_entities[id];
		if(ent) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		lent = Lua_GetEntity(L, 1);
		if(lent == NULL || lent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = lent->e;
	}

	LUA_DEBUG("Mover_HaltAngles - start: ent=%d", ent->s.number);
	if(ent)
	{
		BG_EvaluateTrajectory(&ent->s.apos, level.time, ent->s.apos.trBase);
		ent->s.apos.trType = TR_STATIONARY;
		ent->s.apos.trTime = level.time;
		trap_LinkEntity(ent);
		LUA_DEBUG("Mover_HaltAngles - return: halted ent");
	}

	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #17
0
ファイル: lua_mover.c プロジェクト: gitter-badger/rpgxEF
/***
Stops translational movement on ent immediately.
@function Halt
@param ent Entity or entity number.
@return Success or failure.
*/
static int Mover_Halt(lua_State *L) {
	lent_t		*lent;
	gentity_t	*ent = NULL;
	int			id = 0;
	
	if(lua_isnumber(L, 1)) {
		id =  luaL_checkint(L, 1);
		if(id < 0 || id > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = &g_entities[id];
		if(ent == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		lent = Lua_GetEntity(L, 1);
		if(lent == NULL || lent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = lent->e;
	}

	LUA_DEBUG("Mover_Halt - start: end=%d", ent->s.number);
	BG_EvaluateTrajectory(&ent->s.pos, level.time, ent->r.currentOrigin);
	VectorCopy(ent->r.currentOrigin, ent->s.pos.trBase);
	ent->s.pos.trType = TR_STATIONARY;
	ent->s.pos.trTime = level.time;
	ent->nextthink = 0;
	ent->think = NULL;
	ent->nextTrain = NULL;
	trap_LinkEntity(ent);
	LUA_DEBUG("Mover_Halt - return: halted ent");
	lua_pushboolean(L, qtrue);
	return 1;
}
コード例 #18
0
ファイル: lua_game.c プロジェクト: gitter-badger/rpgxEF
/***
Prints text to the servers console.
@function Print
@param test Text to print.
*/
static int Game_Print(lua_State *L) {
	int		i;
	char	buf[MAX_STRING_CHARS];
	int		n = lua_gettop(L);

	memset(buf, 0, sizeof(buf));

	lua_getglobal(L, "tostring");

	LUA_DEBUG("BEGIN - game.Print");

	for(i = 1; i <= n; i++)
	{
		const char     *s;

		lua_pushvalue(L, -1);
		lua_pushvalue(L, i);
		lua_call(L, 1, 1);
		s = lua_tostring(L, -1);

		if(s == NULL)
		{
			LUA_DEBUG("ERROR - game.Print - no string");
			return 1;
		}

		Q_strcat(buf, sizeof(buf), s);

		lua_pop(L, 1);
	}

	G_Printf("%s\n", buf);

	LUA_DEBUG("END - game.Print");
	return 0;
}
コード例 #19
0
ファイル: lua_misc.cpp プロジェクト: dbt1/neutrino-mp
int CLuaInstMisc::strFind(lua_State *L)
{
	/* workaround for deprecated functions */
	CLuaMisc *D;
	if (luaL_testudata(L, 1, LUA_CLASSNAME) == NULL) {
		D = MiscCheckData(L, 1);
		if (!D) return 0;
	}
	/* CLuaMisc *D = MiscCheckData(L, 1);
	if (!D) return 0; */
	int numargs = lua_gettop(L);
	if (numargs < 3) {
		printf("CLuaInstMisc::%s: not enough arguments (%d, expected 2 (or 3 or 4))\n", __func__, numargs);
		lua_pushnil(L);
		return 1;
	}
	const char *s1;
	const char *s2;
	int pos=0, n=0, ret=0;
	s1 = luaL_checkstring(L, 2);
	s2 = luaL_checkstring(L, 3);
	if (numargs > 3)
		pos = luaL_checkint(L, 4);
	if (numargs > 4)
		n = luaL_checkint(L, 5);

	std::string str(s1);
	if (numargs > 4)
		ret = str.find(s2, pos, n);
	else
		ret = str.find(s2, pos);

	LUA_DEBUG("####[%s:%d] str_len: %d, s2: %s, pos: %d, n: %d, ret: %d\n", __func__, __LINE__, str.length(), s2, pos, n, ret);
	if (ret == (int)std::string::npos)
		lua_pushnil(L);
	else
		lua_pushinteger(L, ret);
	return 1;
}
コード例 #20
0
ファイル: lua_mover.c プロジェクト: gitter-badger/rpgxEF
/***
Moves an entity like a func_train entity. Targets have to be path_corner entities.
@function AsTrain
@param mover Entity to move.
@param target path_corner entity to move to.
@param speed Speed to move with to the first path_corner.
@return Success or failure.
 */
static int Mover_AsTrain(lua_State * L)
{
	lent_t			*lent, *tlent;
	gentity_t      *ent = NULL;
	gentity_t      *targ = NULL;
	vec3_t          move;
	float           length;
	int				id = 0, tid = 0;

	float           speed = (float)luaL_checknumber(L, 3);

	if(lua_isnumber(L, 1)) {
		id = luaL_checkint(L, 1);
		if(id < 0 || id > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = &g_entities[id];
		if(ent == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		lent = Lua_GetEntity(L, 1);
		if(lent == NULL || lent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		ent = lent->e;
	}
	if(luaL_checkint(L, 2)) {
		tid = luaL_checkint(L, 2);
		if(tid < 0 || tid > MAX_GENTITIES - 1) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		targ = &g_entities[tid];
		if(targ == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
	} else {
		tlent = Lua_GetEntity(L, 2);
		if(!tlent || tlent->e == NULL) {
			lua_pushboolean(L, qfalse);
			return 1;
		}
		targ = tlent->e;
	}

	LUA_DEBUG("Mover_AsTrain - start: ent=%d target=%d speed=%f", ent->s.number, targ->s.number, speed);

	if(ent == NULL || targ == NULL)
	{
		LUA_DEBUG("Mover_AsTrain - return: ent or/and target missing");
		lua_pushboolean(L, qfalse);
		return 1;
	}
	if(speed < 1)
	{
		LUA_DEBUG("Mover_AsTrain - moving: speed less than 1 fixed");
		speed = 1;
	}

	if(ent->nextTrain)
	{
		LUA_DEBUG("Mover_AsTrain - pathing: NextTrain=%d ", ent->nextTrain->s.number);
	}

	ent->speed = speed;
	ent->nextTrain = targ;
	ent->reached = Reached_Train;
	ent->target = G_NewString(targ->targetname);

	Think_SetupTrainTargets(ent);

	BG_EvaluateTrajectory(&ent->s.pos, level.time, ent->r.currentOrigin);
	VectorCopy(ent->r.currentOrigin, ent->s.origin);

	VectorCopy(ent->s.origin, ent->pos1);
	VectorCopy(ent->nextTrain->s.origin, ent->pos2);

	VectorSubtract(ent->pos2, ent->pos1, move);
	length = VectorLength(move);

	if(length <= 0.05)
	{
		G_SetOrigin(ent, ent->pos2);
		LUA_DEBUG("Mover_AsTrain - return: snapped to target, length too small length=%f", length);
		lua_pushboolean(L, qtrue);
		return 1;
	}

	ent->s.pos.trDuration = length * 1000 / speed;

	ent->s.loopSound = ent->nextTrain->soundLoop;

	SetMoverState(ent, MOVER_1TO2, level.time);

	LUA_DEBUG("Mover_AsTrain - return: moving to target, length=%f duration=%d", length, ent->s.pos.trDuration);
	lua_pushboolean(L, qtrue);
	return 1;
}