03.03.2017, 10:25
Quote:
Because PAWN is not object oriented, PAWN is simple, PAWN is outdated (the version SAMP uses is probably 10 years old), and more ..
I didn't "fail", I've been testing PAWN limits for months now, and I'm saying there is no way to process with a REAL modular design, yeah you could shit yourself and make some files called "callbacks, commands, header" separate then include to main file, but this isn't modular. I'm not just a beginner scripter, it's just the language that lacks the required features to make it modular. Adding some hooks and functions in different files, isn't what Modular design is. Anyways, that's my last reply here, I've said what I wanted to. |
Hooks, functions, macros, variables etc. should be kept together in one file when they are for the same logical part of code (semantics - meaning, instead of syntax - appearance). If you have a variable storing the owner of a vehicle, and a function to sell a vehicle - put them in the same file, named something like "VehicleOwnership.pwn". If you have another variable storing the last person to kill someone, that has probably got nothing at all to do with vehicle ownership and should go in a totally separate file. Yes, they are both variables. Yes, they might look very similar, so you can do:
PHP Code:
new gVehicleOwner;
new gLastKillerID;
The best way I have found to keep things modular is static variables. Make all the globals in one file "static" and only provide access through a function API:
PHP Code:
static
gVehicleOwner[MAX_VEHICLES] = { INVALID_PLAYER_ID, ... };
bool:VO_SetOwner(vehicleid, playerid)
{
// Already owned.
if (gVehicleOwner[vehicleid] != INVALID_PLAYER_ID)
return false;
gVehicleOwner[vehicleid] = playerid;
return true;
}
VO_GetOwner(vehicleid)
{
return gVehicleOwner[vehicleid];
}
PHP Code:
static
Iterator:gOwnedVehicles<MAX_PLAYERS, MAX_VEHICLES>;
bool:VO_SetOwner(vehicleid, playerid)
{
// Already owned.
if (Iter_Contains(gOwnedVehicles<>, vehicleid))
return false;
Iter_Add(gOwnedVehicles<playerid>, vehicleid);
return true;
}
VO_GetOwner(vehicleid)
{
new
ret = Iter_GetMulti(gOwnedVehicles<>, vehicleid);
return (ret == -1) ? INVALID_PLAYER_ID : ret;
}
Some good examples of modular modes and includes:
YSI (obviously). Look through that and take a guess at what "y_inline.inc", "y_foreach.inc", and "y_commands.inc" do. They do often have a second file of (say) "y_commands/impl.inc", but it is always just "impl.inc" (short for "implementation") and never split up further in to variables and functions in separate files, because then you can't use statics, and then you can't KNOW that no-one else is directly accessing your private internal state. Even the tests don't (usually) have access to internal state, because they test the external API ("VO_SetOwner" and "VO_GetOwner" above), not the implementation (again, usually).
https://github.com/Zeex/amx_assembly Designed very purely, so actually has very little global state (variables) at all anywhere.
https://github.com/Southclaws/ScavengeSurvive Already mentioned, but worth repeating. Again, see how all the files are named for the gamemode system they implement, not what the code in them looks like. A file for macros, another file for functions, that's just totally useless - like classifying vehicles by their colour because a red van and a red car have a superficially similar appearance (as functions do to other functions), instead of by use.