Quote:
Originally Posted by KWo
dll.cpp
286: m_spriteTexture = PRECACHE_MODEL ("sprites/lgtning.spr");
then m_spriteTexture (which - I believe - it's a pointer to the model name string) is used i.e. in util.cpp:
1755: WRITE_SHORT (m_spriteTexture);
|
No. m_spriteTexture it's just a model index (can be used in arrays such as: 'sv.models', 'sv.model_precache', 'sv.model_precache_flags', and God knows where else...) AND THIS IS NOT A POINTER!
See example from HL engine: (It was necessary at once and to lay out, I simply was too lazy)
Code:
int PF_precache_model_I (const char *const modelName)
{
bool v1 (false);
if (modelName == NULL)
Host_Error ("PF_precache_model_I: NULL pointer");
if (PR_IsEmptyString (modelName))
Host_Error ("PF_precache_model_I: Bad string '%s'", modelName);
if (modelName[0u] == '!')
{
++modelName; // Skip '!' character.
v1 = true;
}
unsigned int modelIndex (0u);
if (sv.state == ss_loading)
{
// Check if model with given name already precached....
for (/* Empty */; sv.model_precache[modelIndex] != NULL; ++modelIndex)
{
if (Q_stricmp (sv.model_precache[modelIndex], modelName) == 0)
return modelIndex; // If we find it, return it's index....
// If no free slots left, print error and exit....
if (modelIndex == MAX_MODELS)
Host_Error
(
"PF_precache_model_I: Model '%s' failed to precache because the item count is over the %d limit.\n"
"Reduce the number of brush models and/or regular models in the map to correct this.",
modelName, MAX_MODELS
);
}
// register new model
sv.model_precache[modelIndex] = modelName;
sv.models[modelIndex] = Mod_ForName (modelName, true, true);
if (!v1)
sv.model_precache_flags[modelIndex] |= 1u;
}
else
{
// Check if model with given name already precached....
for (/* Empty */; sv.model_precache[modelIndex] != NULL; ++modelIndex)
{
if (Q_stricmp (sv.model_precache[modelIndex], modelName) == 0)
return modelIndex; // If we find it, return it's index....
if (modelIndex == MAX_MODELS) // We can't precache model when server is running, so if we have not found already precached model with given name, print error and exit....
Host_Error ("PF_precache_model_I: '%s' Precache can only be done in spawn functions", modelName);
}
}
return modelIndex;
}
But I'm talking ONLY about strings, which you pass as arguments in functions (for example see above argument 'modelName') such as 'SET_MODEL', 'PRECACHE_*' and use function ALLOC_STRING instead of MAKE_STRING - that's all.
Quote:
Originally Posted by KWo
So - the question was:
a) should SET_MODEL function should be used the same way - with stored pointer:
now in dll.cpp:
291: SET_MODEL (pent, "models/player/urban/urban.mdl");
but maybe - if I want to use this model name couple of times in code - it should be:
m_model_urban = PRECACHE_MODEL(const_cast<char *>(STRING (ALLOC_STRING ("models/player/urban/urban.mdl"))));
SET_MODEL (pent, m_model_urban);
b) if the model in example a) doesn't need to be precached, because it was already precached somewhere, how the function SET_MODEL should look like?
c) if I want to use the model name once to set - should the example look like:
SET_MODEL(const_cast<char *>(STRING (ALLOC_STRING ("models/player/urban/urban.mdl"))))?
|
All should look as before, except for a code which is below....
Here is complete list of things that you should change in your code:
Code:
int Spawn (edict_t *pent)
{
282: PRECACHE_SOUND (const_cast <char *> (STRING (ALLOC_STRING ("weapons/xbow_hit1.wav")))); // waypoint add
283: PRECACHE_SOUND (const_cast <char *> (STRING (ALLOC_STRING ("weapons/mine_activate.wav")))); // waypoint delete
284: PRECACHE_SOUND (const_cast <char *> (STRING (ALLOC_STRING ("common/wpn_hudon.wav")))); // path add/delete done
285: PRECACHE_SOUND (const_cast <char *> (STRING (ALLOC_STRING ("debris/bustglass1.wav")))); // waypoint error found
286: m_spriteTexture = PRECACHE_MODEL (const_cast <char *> (STRING (ALLOC_STRING ("sprites/lgtning.spr"))));
291: SET_MODEL (pent, const_cast <char *> (STRING (ALLOC_STRING ("models/player/urban/urban.mdl"))));
299: SET_MODEL (pent, const_cast <char *> (STRING (ALLOC_STRING ("models/player/terror/terror.mdl"))));
307: SET_MODEL (pent, const_cast <char *> (STRING (ALLOC_STRING ("models/player/vip/vip.mdl"))));
319: pent->v.target = ALLOC_STRING ("fake");
320: pent->v.targetname = ALLOC_STRING ("fake");
}
void ServerActivate (edict_t *pEdictList, int edictCount, int clientMax)
{
1824: PRECACHE_MODEL("models/mechgibs.mdl");
}
void StartFrame (void)
{
1968: SET_MODEL (pClient->pIllumEnt, const_cast <char *> (STRING (ALLOC_STRING ("models/mechgibs.mdl")))); // sets it a model
}
Quote:
Originally Posted by KWo
if that second ALLOC_STRING leads or doesn't lead to memory leak because of allocating the memory for the same string couple of times - I can feel here some problem.
|
For the engine it is not a problem - it does not lead to memory leaks, but it just will reserve more space in memory than necessary. It means that in memory reserved by the engine will store so much identical strings, how many and entities in game. (for example string "models/mechgibs.mdl" - for each bot).
But it can be bypassed easily, in such a way: (just a example, you can write something more pretty)
Code:
enum String_t
{
String_xbow_hit1,
String_mine_activate,
String_wpn_hudon,
String_bustglass1,
String_lgtning,
String_urban,
String_terror,
String_vip,
String_fake,
String_mechgibs,
String_Total
};
char *strings[String_Total] =
{
"weapons/xbow_hit1.wav",
"weapons/mine_activate.wav",
"common/wpn_hudon.wav",
"debris/bustglass1.wav",
"sprites/lgtning.spr",
"models/player/urban/urban.mdl",
"models/player/terror/terror.mdl",
"models/player/vip/vip.mdl",
"fake",
"models/mechgibs.mdl"
};
void GameDLLInit (void)
{
// ...
for (unsigned char stringIndex (0u); stringIndex < String_Total; ++stringIndex)
strings[stringIndex] = const_cast <char *> (STRING (ALLOC_STRING (strings[stringIndex])));
// ...
}
int Spawn (edict_t *pent)
{
282: PRECACHE_SOUND (strings[String_xbow_hit1]); // waypoint add
283: PRECACHE_SOUND (strings[String_mine_activate]); // waypoint delete
284: PRECACHE_SOUND (strings[String_wpn_hudon]); // path add/delete done
285: PRECACHE_SOUND (strings[String_bustglass1]); // waypoint error found
286: m_spriteTexture = PRECACHE_MODEL (strings[String_lgtning]);
291: SET_MODEL (pent, strings[String_urban]);
299: SET_MODEL (pent, strings[String_terror]);
307: SET_MODEL (pent, strings[String_vip]);
319: pent->v.target = MAKE_STRING (strings[String_fake]);
320: pent->v.targetname = MAKE_STRING (strings[String_fake]);
}
void ServerActivate (edict_t *pEdictList, int edictCount, int clientMax)
{
1824: PRECACHE_MODEL(strings[String_mechgibs]);
}
void StartFrame (void)
{
1968: SET_MODEL (pClient->pIllumEnt, strings[String_mechgibs]); // sets it a model
}
Quote:
Originally Posted by KWo
b) after succesful unloading podbot_mm.dll all slots used by bots still are in use (also You can see not moving bots on the server - like clients away from the keyboard - how to remove them automatically while using meta unload command?
|
You must first (before calling function BotFreeAllMemory() in Meta_Detach() (line = 206)) kick all the bots:
Code:
PbCmdParser (NULL, g_rgpszPbCmds[PBCMD_REMOVEBOTS], NULL, NULL, NULL, NULL, NULL);
Code:
C_DLLEXPORT int Meta_Detach (PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
{
// this function is called when metamod unloads the plugin. A basic check is made in order
// to prevent unloading the plugin if its processing should not be interrupted.
// is metamod allowed to unload the plugin ?
if ((now > Plugin_info.unloadable) && (reason != PNL_CMD_FORCED))
{
LOG_CONSOLE (PLID, "%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name);
LOG_ERROR (PLID, "%s: plugin NOT detaching (can't unload plugin right now)", Plugin_info.name);
return (FALSE); // returning FALSE prevents metamod from unloading this plugin
}
// Remove all bots from game....
PbCmdParser (NULL, g_rgpszPbCmds[PBCMD_REMOVEBOTS], NULL, NULL, NULL, NULL, NULL);
// Delete all allocated Memory
BotFreeAllMemory();
return (TRUE); // returning TRUE enables metamod to unload this plugin
}
NOTE: allocation of memory for a classname of the entity isn't necessary for the CREATE_NAMED_ENTITY function