2019-08-31 19:18:15 -07:00
/*
2024-02-13 22:51:36 -08:00
* Copyright (c) 2016-2023 Vera Visions LLC.
2019-08-31 19:18:15 -07:00
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2022-07-07 09:10:14 -07:00
*/
2018-12-30 17:00:38 -08:00
2023-03-13 01:29:18 -07:00
/*!QUAKED trigger_transition (.5 .5 .5) ?
2022-12-13 17:52:20 -08:00
# OVERVIEW
2023-11-17 18:54:46 -08:00
Defines level transition regions.
2024-02-23 13:54:46 -08:00
All entities touching this volume will carry across to the next level.
2020-10-25 04:38:41 -07:00
2022-12-13 17:52:20 -08:00
# KEYS
- "targetname" : Name
2021-07-14 02:49:30 -07:00
2023-11-17 18:54:46 -08:00
# NOTES
2024-02-23 13:54:46 -08:00
In order for this entity to work, one has to assign a working info_landmark entity to a trigger_changelevel, and give this entity the same targetname as said landmark.
2023-11-17 18:54:46 -08:00
2022-12-13 17:52:20 -08:00
# TRIVIA
2020-10-25 04:38:41 -07:00
This entity was introduced in Half-Life (1998).
2019-09-06 20:37:06 -07:00
*/
2022-08-10 14:24:06 -07:00
class
trigger_transition:NSBrushTrigger
2018-12-30 17:00:38 -08:00
{
2023-11-17 18:54:46 -08:00
public:
2022-12-06 15:04:07 -08:00
void trigger_transition(void);
2023-11-17 18:54:46 -08:00
/* overrides */
2022-12-06 15:04:07 -08:00
virtual void Respawn(void);
2023-11-17 18:54:46 -08:00
2024-02-13 22:51:36 -08:00
nonvirtual void SaveTransition(entity, bool);
2023-09-28 18:40:06 -07:00
nonvirtual NSEntity FindCarrierEntity(string);
nonvirtual void LoadTransition(void);
2018-12-30 17:00:38 -08:00
};
2020-04-12 06:50:42 -07:00
void
2022-08-10 14:24:06 -07:00
trigger_transition::trigger_transition(void)
2018-12-30 17:00:38 -08:00
{
2021-10-19 16:18:36 -07:00
}
2020-11-13 02:17:42 -08:00
2021-10-19 16:18:36 -07:00
void
2022-08-10 14:24:06 -07:00
trigger_transition::Respawn(void)
2021-10-19 16:18:36 -07:00
{
2022-08-10 14:24:06 -07:00
InitBrushTrigger();
2023-10-30 16:37:45 -07:00
SetSolid(SOLID_NOT);
2019-03-19 12:01:24 -07:00
}
2023-09-28 18:40:06 -07:00
void
2024-02-13 22:51:36 -08:00
trigger_transition::SaveTransition(entity pvsTest, bool usePVS)
2023-09-28 18:40:06 -07:00
{
int i = 0i;
filestream transFile = fopen("trans.dat", FILE_WRITE);
if (transFile < 0) {
error("Unable to write trans.dat for transitioning.");
}
/* loop through all entities */
for (NSEntity a = __NULL__; (a = (NSEntity)findfloat(a, ::identity, 1));) {
2024-02-13 22:51:36 -08:00
bool replicateEntity = false;
2024-03-02 00:40:08 -08:00
bool continueInNextMap = false;
/* no classname? never allow */
if not (a.classname) {
continue;
}
2024-02-13 22:51:36 -08:00
//print(sprintf("TRANSITION: %i %S %S\n", i, a.classname, a.m_strGlobalName));
2023-09-28 18:40:06 -07:00
2024-03-02 00:40:08 -08:00
/* if we're using the PVS, use the info_landmark as a reference */
if (usePVS == true) {
if (checkpvs(pvsTest.origin, a) == true) {
2024-02-13 22:51:36 -08:00
replicateEntity = true;
2023-09-28 18:40:06 -07:00
2024-02-13 22:51:36 -08:00
if (a.classname == "info_landmark") {
replicateEntity = false;
}
/* to get rid of the 'out of model slots' error */
if (a.model == "" && solid != SOLID_NOT) {
replicateEntity = false;
2024-03-02 00:40:08 -08:00
continueInNextMap = false;
2024-02-13 22:51:36 -08:00
}
}
} else if (WithinBounds(a) == true) {
replicateEntity = true;
}
2024-03-04 20:13:53 -08:00
/* these checks are somewhat safe assumptions. */
if (a.classname == "player") {
replicateEntity = false;
continueInNextMap = false;
}
2024-03-02 00:40:08 -08:00
/* only carry brushes with a global name */
if (a.m_bIsBrush == true) {
replicateEntity = false;
continueInNextMap = false;
}
/* global name = always find target in next map */
if (a.m_strGlobalName) {
continueInNextMap = true;
replicateEntity = false;
}
2024-02-13 22:51:36 -08:00
if (replicateEntity == true) {
2023-09-28 18:40:06 -07:00
fputs(transFile, sprintf("ENTITY \"%i\" %S\n", i, a.classname));
fputs(transFile, "{\n");
a.Save(transFile);
fputs(transFile, "}\n");
2024-03-02 00:40:08 -08:00
} else if (continueInNextMap == true) {
2023-09-28 18:40:06 -07:00
fputs(transFile, sprintf("CONTINUE \"%i\" %S\n", i, a.m_strGlobalName));
fputs(transFile, "{\n");
a.Save(transFile);
fputs(transFile, "}\n");
2024-02-13 22:51:36 -08:00
} else {
continue;
2023-09-28 18:40:06 -07:00
}
2024-02-13 22:51:36 -08:00
2023-09-28 18:40:06 -07:00
i++;
}
fclose(transFile);
}
NSEntity
trigger_transition::FindCarrierEntity(string globalName)
{
for (NSEntity a = __NULL__; (a = (NSEntity)findfloat(a, ::identity, 1));) {
if (a.m_strGlobalName == globalName) {
return a;
}
}
2024-03-02 00:40:08 -08:00
return (__NULL__);
2023-09-28 18:40:06 -07:00
}
vector Landmark_GetPosition(void);
2024-03-02 00:40:08 -08:00
2023-09-28 18:40:06 -07:00
void
trigger_transition::LoadTransition(void)
{
string lineFeed;
2024-02-13 22:51:36 -08:00
bool isNew = false;
2023-09-28 18:40:06 -07:00
NSEntity carrierEntity = __NULL__;
filestream transFile = fopen("trans.dat", FILE_READ);
if (transFile < 0) {
2024-03-02 00:40:08 -08:00
NSError("Called to transition, but trans.dat does not exist.");
2023-09-28 18:40:06 -07:00
}
2024-03-02 00:40:08 -08:00
NSLog("Found transition file. Will transition over entities.");
2023-09-28 18:40:06 -07:00
while ((lineFeed = fgets(transFile))) {
int c = tokenize(lineFeed);
/* start of an entity */
if (argv(0) == "{") {
continue;
} else if (argv(0) == "}") {
2024-03-02 00:40:08 -08:00
if (carrierEntity.solid == 0 && carrierEntity.movetype == 0) {
carrierEntity.Destroy();
carrierEntity = __NULL__;
}
if (carrierEntity) {
carrierEntity.TransitionComplete();
carrierEntity.SendFlags = -1;
carrierEntity = __NULL__;
}
2023-09-28 18:40:06 -07:00
continue;
}
if (c == 3) {
if (argv(0) == "CONTINUE") {
carrierEntity = FindCarrierEntity(argv(2));
2024-02-13 22:51:36 -08:00
isNew = false;
2023-09-28 18:40:06 -07:00
} else if (argv(0) == "ENTITY") {
2024-03-02 00:40:08 -08:00
string desiredClass = argv(2);
if (desiredClass == "corpse") {
carrierEntity = __NULL__;
continue;
}
carrierEntity = Entity_CreateClass(desiredClass);
2024-02-13 22:51:36 -08:00
isNew = true;
2023-09-28 18:40:06 -07:00
}
} else if (c == 2) { /* key value pairs */
if (carrierEntity) {
switch (argv(0)) {
case "model":
2024-03-02 00:40:08 -08:00
carrierEntity.model = argv(1);
2023-09-28 18:40:06 -07:00
case "modelindex":
break;
#if 0
case "origin":
vector newOrigin = stov(argv(1)) + Landmark_GetPosition();
print(sprintf("Offsetting %S by %v\n", carrierEntity.m_strGlobalName, Landmark_GetPosition()));
2023-10-04 07:54:43 -07:00
carrierEntity.m_vecRestoredOrigin = newOrigin;
2023-09-28 18:40:06 -07:00
carrierEntity.Restore("origin", vtos(newOrigin));
break;
#endif
default:
carrierEntity.Restore(argv(0), argv(1));
}
}
}
}
fremove("trans.dat");
2024-02-13 22:51:36 -08:00
}
void
trigger_transition_pvsfallback(entity pvsTest)
{
trigger_transition::SaveTransition(pvsTest, true);
2023-09-28 18:40:06 -07:00
}