2016-03-27 11:49:47 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "q_shared.h"
|
|
|
|
#include "qcommon.h"
|
|
|
|
#include "alias.h"
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
static AliasList_t* Aliases;
|
|
|
|
static AliasListNode_t* foundlist[64];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* AliasListNode_New()
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* node = Z_TagMalloc(sizeof(AliasListNode_t), TAG_TIKI);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
memset(node, 0, sizeof(AliasListNode_t));
|
2016-03-27 11:49:47 +02:00
|
|
|
node->weight = 1.0f;
|
|
|
|
node->next = NULL;
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasList_t* AliasList_New(const char* name)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasList_t* list = Z_TagMalloc(sizeof(AliasList_t), TAG_TIKI);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
list->num_in_list = 0;
|
|
|
|
list->sorted_list = NULL;
|
|
|
|
list->data_list = NULL;
|
|
|
|
list->dirty = qfalse;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (name)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
strncpy(list->name, name, sizeof(list->name));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
list->name[0] = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListClear(AliasList_t* list)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* node;
|
|
|
|
AliasListNode_t* next;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (list->sorted_list)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Z_Free(list->sorted_list);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (node = list->data_list; node != NULL; node = next)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
next = node->next;
|
2023-02-01 00:28:40 +01:00
|
|
|
Z_Free(node);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
list->num_in_list = 0;
|
|
|
|
list->dirty = qfalse;
|
|
|
|
list->sorted_list = NULL;
|
|
|
|
list->data_list = NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListDelete(AliasList_t* list)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Alias_ListClear(list);
|
|
|
|
Z_Free(list);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
float getTokenFloat(const char** parameters, char* parmName, AliasListNode_t* node)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* token;
|
2016-03-27 11:49:47 +02:00
|
|
|
float temp_float = 0.0f;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
token = COM_GetToken((char**)parameters, 1);
|
2023-06-17 02:09:56 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (token && *token)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-06-17 02:09:56 +02:00
|
|
|
temp_float = (float)atof(token);
|
2023-02-01 00:28:40 +01:00
|
|
|
if (temp_float < 0.0f)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("ERROR getTokenFloat: %s value out of range in %s alias\n", parmName, node->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return temp_float;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("ERROR getTokenFloat: %s value is hosed or wasn't found for %s\n", parmName, node->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
int S_ChannelNameToNum(const char* pszName)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!Q_stricmp(pszName, "auto"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_AUTO;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "local"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_LOCAL;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "weapon"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_WEAPON;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "voice"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_VOICE;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "item"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_ITEM;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "body"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_BODY;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "dialog"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_DIALOG;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "dialog_secondary"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_DIALOG_SECONDARY;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "weaponidle"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_WEAPONIDLE;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (!Q_stricmp(pszName, "menu"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return CHAN_MENU;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* S_ChannelNumToName(int iChannel)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
switch (iChannel)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
case CHAN_AUTO:
|
|
|
|
return "auto";
|
|
|
|
case CHAN_LOCAL:
|
|
|
|
return "local";
|
|
|
|
case CHAN_WEAPON:
|
|
|
|
return "weapon";
|
|
|
|
case CHAN_VOICE:
|
|
|
|
return "voice";
|
|
|
|
case CHAN_ITEM:
|
|
|
|
return "item";
|
|
|
|
case CHAN_BODY:
|
|
|
|
return "body";
|
|
|
|
case CHAN_DIALOG:
|
|
|
|
return "dialog";
|
|
|
|
case CHAN_DIALOG_SECONDARY:
|
|
|
|
return "dialog_secondary";
|
|
|
|
case CHAN_WEAPONIDLE:
|
|
|
|
return "weaponidle";
|
|
|
|
case CHAN_MENU:
|
|
|
|
return "menu";
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* token;
|
2016-03-27 11:49:47 +02:00
|
|
|
float temp_float;
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* nptr;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!node || !parameters)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-05-20 20:33:58 +02:00
|
|
|
for (;;)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-05-20 20:33:58 +02:00
|
|
|
token = nptr = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !token[0])
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-05-20 20:33:58 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Q_stricmp(token, "stop"))
|
|
|
|
{
|
|
|
|
node->stop_flag = 1;
|
|
|
|
}
|
|
|
|
else if (!Q_stricmp(token, "soundparms"))
|
|
|
|
{
|
|
|
|
node->volume = getTokenFloat(¶meters, "volume", node);
|
|
|
|
node->volumeMod = getTokenFloat(¶meters, "volumeMod", node);
|
|
|
|
node->pitch = getTokenFloat(¶meters, "pitch", node);
|
|
|
|
node->pitchMod = getTokenFloat(¶meters, "pitchMod", node);
|
|
|
|
node->dist = getTokenFloat(¶meters, "dist", node);
|
|
|
|
node->maxDist = getTokenFloat(¶meters, "maxDist", node);
|
|
|
|
|
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
node->channel = S_ChannelNameToNum(token);
|
|
|
|
if (node->channel == -1)
|
|
|
|
{
|
|
|
|
Com_Printf("%s is not avalid channel on %s alias.\n", token, node->alias_name);
|
|
|
|
node->channel = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
|
|
|
{
|
|
|
|
Com_Printf("ERROR: defaulting %s to not streamed - please setup alias properly.\n", node->alias_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Q_stricmp(token, "streamed"))
|
|
|
|
{
|
|
|
|
node->streamed = qtrue;
|
|
|
|
}
|
|
|
|
else if (!Q_stricmp(token, "loaded"))
|
|
|
|
{
|
|
|
|
node->streamed = qfalse;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Com_Printf("ERROR: Expecting streamed or loaded in ubersound and got %s on alias %s\n", token, node->alias_name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2023-05-28 20:59:42 +02:00
|
|
|
else if (!Q_stricmp(token, "subtitle") || !Q_stricmp(token, "forcesubtitle"))
|
2023-05-20 20:33:58 +02:00
|
|
|
{
|
2024-09-21 21:08:43 +02:00
|
|
|
size_t size;
|
|
|
|
|
2023-05-28 20:59:42 +02:00
|
|
|
if (!Q_stricmp(token, "subtitle")) {
|
|
|
|
node->forcesubtitle = qfalse;
|
|
|
|
} else {
|
|
|
|
node->forcesubtitle = qtrue;
|
|
|
|
}
|
|
|
|
|
2023-05-20 20:33:58 +02:00
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
|
|
|
{
|
|
|
|
Com_Printf("NULL subtitle on %s alias.\n", node->alias_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-09-21 21:08:43 +02:00
|
|
|
size = strlen(token) + 1;
|
|
|
|
node->subtitle = Z_TagMalloc(size, TAG_TIKI);
|
|
|
|
memcpy(node->subtitle, token, size);
|
2023-05-20 20:33:58 +02:00
|
|
|
}
|
|
|
|
else if (!Q_stricmp(token, "pitch"))
|
|
|
|
{
|
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-17 02:09:56 +02:00
|
|
|
temp_float = (float)atof(token);
|
2023-05-20 20:33:58 +02:00
|
|
|
if (temp_float < 0.0f)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-05-20 20:33:58 +02:00
|
|
|
Com_Printf("Pitch value out of range in %s alias\n", node->alias_name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
node->pitch = temp_float;
|
|
|
|
}
|
|
|
|
else if (!Q_stricmp(token, "pitchmod"))
|
|
|
|
{
|
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
|
|
|
{
|
|
|
|
return;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-06-17 02:09:56 +02:00
|
|
|
temp_float = (float)atof(token);
|
2023-05-20 20:33:58 +02:00
|
|
|
if (temp_float < 0.0f)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-05-20 20:33:58 +02:00
|
|
|
Com_Printf("PitchMod value out of range in %s alias\n", node->alias_name);
|
|
|
|
continue;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-05-20 20:33:58 +02:00
|
|
|
node->pitchMod = temp_float;
|
|
|
|
}
|
|
|
|
else if (!Q_stricmp(token, "volumemod"))
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-17 02:09:56 +02:00
|
|
|
temp_float = (float)atof(token);
|
2023-02-01 00:28:40 +01:00
|
|
|
if (temp_float < 0.0f)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("volumeMod value out of range in %s alias\n", node->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
node->volumeMod = temp_float;
|
|
|
|
}
|
2023-05-20 20:33:58 +02:00
|
|
|
else if (!Q_stricmp(token, "dist"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("\n\n BAD DISTANCE\n\n");
|
2016-03-27 11:49:47 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-17 02:09:56 +02:00
|
|
|
temp_float = (float)atof(token);
|
2023-02-01 00:28:40 +01:00
|
|
|
if (temp_float < 0.0f)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("dist value out of range in %s alias\n", node->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
node->dist = temp_float;
|
|
|
|
}
|
2023-05-20 20:33:58 +02:00
|
|
|
else if (!Q_stricmp(token, "channel"))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
token = COM_GetToken((char**)¶meters, qtrue);
|
|
|
|
if (!token || !*token)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("\n\n BAD DISTANCE\n\n");
|
2016-03-27 11:49:47 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
node->channel = S_ChannelNameToNum(token);
|
|
|
|
if (node->channel == -1)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("%s is not a valid channel on %s alias.\n", token, node->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
node->channel = CHAN_AUTO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_Printf("Unknown parameter for %s alias\n", node->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
qboolean Alias_ListAdd(AliasList_t* list, const char* alias, const char* name, const char* parameters)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* ptr = NULL;
|
2016-03-27 11:49:47 +02:00
|
|
|
int i;
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* node;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!list)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (list->dirty)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
for (node = list->data_list; node != NULL; node = node->next)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!strcmp(node->alias_name, alias))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2024-09-08 18:22:12 +02:00
|
|
|
Com_DPrintf("DUPLICATE ALIASES: %s and %s\n", node->alias_name, alias);
|
2016-03-27 11:49:47 +02:00
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
ptr = Alias_ListFindNode(list, alias);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!ptr)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
node = AliasListNode_New();
|
2023-02-01 00:28:40 +01:00
|
|
|
strncpy(node->alias_name, alias, sizeof(node->alias_name));
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (i = 0; i < MAX_ALIASLIST_NAME_LENGTH; i++)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
node->alias_name[i] = tolower(node->alias_name[i]);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
strncpy(node->real_name, name, sizeof(node->real_name));
|
2016-03-27 11:49:47 +02:00
|
|
|
node->stop_flag = 0;
|
2023-02-01 00:28:40 +01:00
|
|
|
Alias_ListAddParms(node, parameters);
|
2016-03-27 11:49:47 +02:00
|
|
|
list->dirty = qtrue;
|
|
|
|
list->num_in_list++;
|
|
|
|
node->next = list->data_list;
|
|
|
|
list->data_list = node;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (strcmp(name, ptr->real_name))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_DPrintf("Duplicate Aliases for %s in list %s.\n", alias, name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListSort(AliasList_t* list)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
int num;
|
|
|
|
int size;
|
|
|
|
int i;
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* root;
|
|
|
|
AliasListNode_t* ptr;
|
|
|
|
AliasListNode_t* smallest = NULL;
|
|
|
|
AliasListNode_t* prev;
|
|
|
|
AliasListNode_t* smallprev;
|
|
|
|
AliasListNode_t* last = NULL;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!list->dirty)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = 0;
|
|
|
|
|
|
|
|
root = list->data_list;
|
|
|
|
list->data_list = NULL;
|
2023-02-01 00:28:40 +01:00
|
|
|
if (list->sorted_list)
|
|
|
|
Z_Free(list->sorted_list);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
size = list->num_in_list * sizeof(AliasListNode_t*);
|
|
|
|
list->sorted_list = Z_TagMalloc(size, TAG_TIKI);
|
|
|
|
memset(list->sorted_list, 0, size);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (i = 0; i < list->num_in_list; i++)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
prev = root;
|
|
|
|
smallprev = root;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (ptr = root->next; ptr != NULL; ptr = ptr->next)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (strcmp(ptr->alias_name, smallprev->alias_name) < 0)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
smallest = prev;
|
|
|
|
smallprev = ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
prev = ptr;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (smallprev == root)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
root = smallprev->next;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
smallest->next = smallprev->next;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!last || strcmp(last->alias_name, smallprev->alias_name))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
list->sorted_list[num++] = smallprev;
|
2016-03-27 11:49:47 +02:00
|
|
|
smallprev->next = list->data_list;
|
|
|
|
list->data_list = smallprev;
|
|
|
|
last = smallprev;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (strcmp(last->real_name, smallprev->real_name))
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_DPrintf("Duplicate Aliases for %s in list %s Last: %p.\n", last->alias_name, list->name, last);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
Z_Free(smallprev);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
list->dirty = 0;
|
|
|
|
list->num_in_list = num;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* Alias_ListFind(AliasList_t* list, const char* alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* node = Alias_ListFindNode(list, alias);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (node)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return node->real_name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListUpdateDialog(AliasList_t* list, const char* alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
int min_index;
|
|
|
|
int max_index;
|
|
|
|
float total_weight;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
Alias_ListFindRandomRange(list, alias, &min_index, &max_index, &total_weight);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* Alias_ListFindNode(AliasList_t* list, const char* alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
char convalias[40];
|
2016-03-27 11:49:47 +02:00
|
|
|
int index;
|
|
|
|
int l;
|
|
|
|
int r;
|
|
|
|
int diff;
|
|
|
|
size_t length;
|
|
|
|
int __res;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (list->dirty)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
Alias_ListSort(list);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
length = strlen(alias);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (index = 0; index < length; index++)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
convalias[index] = tolower(alias[index]);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
convalias[length] = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
r = 0;
|
|
|
|
l = list->num_in_list - 1;
|
2023-02-01 00:28:40 +01:00
|
|
|
for (index = l; index >= 0; index--)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
__res = (l + r) >> 1;
|
|
|
|
diff = strcmp(convalias, list->sorted_list[index]->alias_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (diff == 0)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
return list->sorted_list[index];
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (diff > 0)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
r = __res + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l = __res - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
float randweight()
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
return ((float)(rand() & 0x7fff)) / ((float)0x8000);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* Alias_ListFindRandom(AliasList_t* list, const char* alias, AliasListNode_t** ret)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
int min_index;
|
|
|
|
int max_index;
|
|
|
|
float total_weight;
|
|
|
|
int i;
|
|
|
|
int numfound;
|
|
|
|
float weight;
|
|
|
|
float num;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!*alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
Alias_ListFindRandomRange(list, alias, &min_index, &max_index, &total_weight);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (min_index == -1 || max_index == -1)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
num = 0.0f;
|
|
|
|
numfound = max_index - min_index + 1;
|
|
|
|
weight = randweight() * total_weight;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (i = 0; i < numfound; i++)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
num += list->sorted_list[i + min_index]->weight;
|
|
|
|
if (num > weight)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (ret)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
*ret = list->sorted_list[i + min_index];
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
return list->sorted_list[i + min_index]->real_name;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_index, int* max_index, float* total_weight)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
char convalias[MAX_ALIASLIST_NAME_LENGTH];
|
2016-03-27 11:49:47 +02:00
|
|
|
int index;
|
|
|
|
int l;
|
|
|
|
int r;
|
|
|
|
int diff;
|
|
|
|
int i;
|
|
|
|
size_t length;
|
|
|
|
int numfound;
|
|
|
|
float totalfoundweight = 0.0f;
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t** ptr;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
*min_index = -1;
|
|
|
|
*max_index = -1;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!*alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
return;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (list->dirty)
|
|
|
|
Alias_ListSort(list);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
length = strlen(alias);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (length > MAX_ALIASLIST_NAME_LENGTH)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (index = 0; index < length; index++)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
convalias[index] = tolower(alias[index]);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
convalias[length] = 0;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-01-30 16:27:38 +01:00
|
|
|
l = 0;
|
|
|
|
r = list->num_in_list - 1;
|
|
|
|
if (r >= 0)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2017-02-19 21:10:06 +01:00
|
|
|
do
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-01-30 16:27:38 +01:00
|
|
|
index = (l + r) >> 1;
|
2023-02-01 00:28:40 +01:00
|
|
|
diff = strncmp(convalias, list->sorted_list[index]->alias_name, length);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (diff == 0)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2023-02-01 00:28:40 +01:00
|
|
|
else if (diff > 0)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-01-30 16:27:38 +01:00
|
|
|
l = index + 1;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-01-30 16:27:38 +01:00
|
|
|
r = index - 1;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
2023-01-30 16:27:38 +01:00
|
|
|
} while (r >= l);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-05-18 19:47:50 +02:00
|
|
|
if (r >= l)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
numfound = 0;
|
2023-01-30 16:27:38 +01:00
|
|
|
*min_index = index;
|
|
|
|
*max_index = index;
|
|
|
|
totalfoundweight = 0.f;
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-01-30 16:27:38 +01:00
|
|
|
ptr = &list->sorted_list[index];
|
2023-05-18 19:47:50 +02:00
|
|
|
for (i = index + 1; i > 0; i--, ptr--)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-01-30 16:27:38 +01:00
|
|
|
if (strncmp(convalias, (*ptr)->alias_name, length)) {
|
2016-03-27 11:49:47 +02:00
|
|
|
break;
|
2023-01-30 16:27:38 +01:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (numfound <= 63 && (*ptr)->alias_name[length] != '_')
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-01-30 16:27:38 +01:00
|
|
|
foundlist[numfound++] = *ptr;
|
|
|
|
totalfoundweight += (*ptr)->weight;
|
2023-05-18 19:47:50 +02:00
|
|
|
*min_index = i - 1;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-30 16:27:38 +01:00
|
|
|
ptr = &list->sorted_list[index + 1];
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (i = index + 1; i < list->num_in_list; i++, ptr++)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-01-30 16:27:38 +01:00
|
|
|
if (strncmp(convalias, (*ptr)->alias_name, length)) {
|
2016-03-27 11:49:47 +02:00
|
|
|
break;
|
2023-01-30 16:27:38 +01:00
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (numfound <= 63 && (*ptr)->alias_name[length] != '_')
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
foundlist[numfound++] = *ptr;
|
|
|
|
totalfoundweight += (*ptr)->weight;
|
2023-01-30 16:27:38 +01:00
|
|
|
*max_index = i;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (numfound)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
*total_weight = totalfoundweight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*min_index = -1;
|
|
|
|
*max_index = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
void Alias_ListDump(AliasList_t* list)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasListNode_t* ptr;
|
2016-03-27 11:49:47 +02:00
|
|
|
int i;
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
if (list->dirty)
|
|
|
|
Alias_ListSort(list);
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_DPrintf("Alias List: %s\n", list->name);
|
|
|
|
Com_DPrintf("Alias Name / Weight / Real Name\n");
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
for (i = 0; i < list->num_in_list; ++i)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
ptr = list->sorted_list[i];
|
|
|
|
Com_DPrintf("%32s %3.2f %s\n", ptr->alias_name, ptr->weight, ptr->real_name);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
Com_DPrintf("%d total aliases\n", list->num_in_list);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* Alias_Find(const char* alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!Aliases) Aliases = AliasList_New("Global");
|
|
|
|
return Alias_ListFind(Aliases, alias);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
qboolean Alias_Add(const char* alias, const char* name, const char* parameters)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!Aliases) Aliases = AliasList_New("Global");
|
|
|
|
return Alias_ListAdd(Aliases, alias, name, parameters);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
qboolean Alias_Delete(const char* alias)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
const char* Alias_FindRandom(const char* alias, AliasListNode_t** ret)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!Aliases) Aliases = AliasList_New("Global");
|
|
|
|
return Alias_ListFindRandom(Aliases, alias, ret);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Alias_Dump()
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!Aliases) Aliases = AliasList_New("Global");
|
|
|
|
Alias_ListDump(Aliases);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void Alias_Clear()
|
|
|
|
{
|
2023-02-01 00:28:40 +01:00
|
|
|
if (!Aliases) Aliases = AliasList_New("Global");
|
|
|
|
Alias_ListClear(Aliases);
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 00:28:40 +01:00
|
|
|
AliasList_t* Alias_GetGlobalList()
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
|
|
|
return Aliases;
|
|
|
|
}
|