Raised This Month: $32 Target: $400
 8% 

[TF2] Biohazard [0.0.3.0] [31/03/20]


Post New Thread Reply   
 
Thread Tools Display Modes
Author
x6herbius
Senior Member
Join Date: May 2011
Location: West Sussex, UK
Plugin ID:
4171
Plugin Version:
0.0.3.0
Plugin Category:
Gameplay
Plugin Game:
Team Fortress 2
Plugin Dependencies:
    Servers with this Plugin:
     
    Plugin Description:
    A TF2 zombie mod styled on the CS:CZ Biohazard mod.
    Old 04-20-2014 , 09:53   [TF2] Biohazard [0.0.3.0] [31/03/20]
    Reply With Quote #1

    I've been sitting on this plugin for over a year now, doing work on it on and off between other things, and while it's not fully finished or polished I thought it might be a good idea to actually release an alpha into the wild and see what people think of it and whether it's worth pursuing. Who knows, it might even be fun.

    So without further ado:

    Team Fortress: Biohazard

    What is it?

    TF Biohazard is a zombie game mode plugin for Team Fortress 2 servers. The survivors (Red) have to hold out for a certain amount of time against the zombies (Blue), who can only use melee. If all survivors fall, the zombies win!

    Hang on! I thought there was already a zombie mode for TF2?

    There is! However, speaking as a previous CS:CZ zombie mod addict, there were a couple of things Zombie Fortress 2 lacked in comparison (at least when I last played it, which was admittedly quite a while ago):
    • When zombified, players died and respawned on the opposite team, in constrast to converting in-place on the battlefield. This ruined the clutch gameplay involved with having a team mate become a zombie in the middle of a densely packed group of players, which was the best part of the original CS mode. TF Biohazard retains this conversion mechanic, meaning team mates who fall to the infection will remain in whatever stronghold you're holding out in until you kill them (or they kill you).
    • Players were limited in their class and weapon choices. In TF Biohazard all 9 classes and (very nearly) all weapons are available for selection - with zombies obviously being limited to melee - allowing you to mix and match your loadouts as you would in a normal TF2 game. Weapon stats and abilities will be tuned as time goes on and gameplay is tested more thoroughly (I've only tested this with a few friends and some bots up until now).

    What maps does the plugin run on?

    TF Biohazard requires maps with a setup and round timer, and ideally multiple locations for Blue players to spawn. It works best with custom-tweaked maps (some of which are linked below), but some maps can theoretically be converted by using a BSP entity editor to lock objectives and add setup and round time. The downside to this method is that it may become easy for Red players to camp the Blue spawn if there is only a single place for zombies to come from - I haven't tested enough to confirm this, so we'll have to wait and see.

    In-depth game mode details

    During setup time, all players are moved to Red and are able to scatter through the map and prepare to hold out against Blue zombies. However, no players know which of them will become zombies until the infection occurs once the setup time has ticked down to zero, so the team mate next to you could spontaneously morph into an enemy and throw a wrench into your defensive plans.

    When a Blue player beats a Red survivor to death, the Red player immediately becomes a zombie. Blue players are able to respawn and their health is modified depending on how many survivors are left alive at the point of spawning - settings are configurable, but the standard modifier is up to 16x the class' base amount of health. The less survivors left alive, the less health each zombie is given.

    On the prototype Offblast map conversion linked below, Blue players are also provided with a short period of spawn protection once leaving their spawns, in pre-emption of sticky traps etc.

    Survivors

    All classes
    • The darker a zombie is coloured, the more health they have. Use this information to pick off weaker targets or prioritise threats.
    • Upon zombification, your class will remain the same. Make a trade-off between the usefulness of your class and loadout as a survivor versus immediately after zombification.
    • When two survivors are left, mini-crits are granted. When only one survivor is left, a speed boost is also granted.

    Weapons disallowed:
    • Cloak and Dagger - replaced with Invis Watch to prevent indefinite invisible camping.
    • Fists of Steel - replaced with Fists as the Fists of Steel cause bugs with zombification.
    • Baby Face's Blaster - replaced with Scattergun to discourage overly tedious Scout chases.

    Scout
    • Hitting a zombie with Mad Milk will apply a penalty to their rage generation rate.

    Pyro
    • Pushing zombies with airblast increases their rage by 3%.

    Engineer
    • Sentries forced to be mini-sentries. TO EVALUATE: add an advantage to using the normal wrench, which ends up building mini-sentries with the metal cost of a normal sentry. Alternatively, evaluate ways of including regular sentries.

    Medic
    • Syringe and crossbow bolt hits add Ubercharge.

    Sniper
    • Hitting a zombie with Jarate will apply a penalty to their rage generation rate.

    Spy
    • Crits and a speed boost are granted on a successful backstab.
    • Disguising as a zombie tints your player model to blend in with the other team.

    Zombies

    All classes
    • Knockback from survivors is increased, and zombies spawn with a health advantage that scales up depending on how many survivors are alive at the time. The respawn frequency of zombies gets longer the less survivors are left alive.
    • Patient Zero zombies (those chosen at the beginning of the round) are granted critical hits for the duration of the round.
    • Pressing space while already airborne will activate a super-jump in order to reach high-up places. For the Scout, the super-jump is activated once all standard double/Atomiser jumps have taken place.
    • Rage builds depending on the average distance from the survivors. Raging will stun any survivors or sentries in the vicinity and will activate temporary crits!

    Non-melee weapons allowed (reskins included):
    • Bonk! Atomic Punch
    • Cloak and Dagger
    • Crit-a-Cola
    • Dead Ringer
    • Disguise Kit
    • Invis Watch
    • Jarate
    • Mad Milk
    • Red-Tape Recorder
    • Sapper

    Melee weapons disallowed:
    • Holiday Punch - replaced with fists to prevent zombies with the Patient Zero crit boost being unable to deal any damage at all if they are the only player on their team. TO EVALUATE: disable Patient Zero crits only when the wearer is the only zombie?

    Engineer
    • Can teleport to a random survivor on rage, when teleport meter is full. TO EVALUATE: bring along an extra player on teleport.

    Pyro
    • Rage also ignites players.

    Heavy
    • Crouching negates weapon knockback.

    Medic
    • Raging grants surrounding players mini-crits.

    Sniper
    • Jarate jar explosions push players, allowing you to knock them off high perch points.

    Spy
    • Crits and a speed boost are granted on a successful backstab, and rage is filled to 100%.
    • Disguising as a survivor removes your player model tint.

    Planned future improvements - under evaluation
    • Sounds/effects/general polish.
    • Make Blue players use the actual Halloween zombie skins. Apparently this isn't possible. :c
    • Allow survivors to select the class they wish to change to upon zombification.
    • Increase sticky launcher reload speed by 50%.
    • Increase minigun firing speed by 25%.
    • Have zombie Ubersaw hits grant 25% rage.

    Details for server admins

    Dependencies

    The plugin requires the following to be installed on the server:

    Installation

    To install, extract the following to your /tf directory. Alternatively, a local attachment of this zip is listed at the end of this post.
    http://www.mediafire.com/file/ryhfuk...0.3.0.zip/file

    Maps are in BZ2 format for easier hosting and downloading.

    Configuration

    The plugin contains a whole host of convars in order to tweak the game experience. You'll probably want to change these as testing progresses to help balance the mode. Report back with good configurations if you wish, in order to help inform the plugin's default values.

    NOTE: Most of these convars take effect immediately, but some may require a round restart/player resupply, or even a map change.

    tfbh_version - Plugin version.

    tfbh_enabled [Def. 1] - Enables or disables the plugin.

    tfbh_debug [Def. 0] - Bit mask for debugging output options. Sum the flags of the ouput you want and stick the value in this convar. Current flags are:

    Code:
    DEBUG_GENERAL       (1 << 0)    // General debugging. 1
    DEBUG_TEAMCHANGE    (1 << 1)    // Debugging team changes. 2
    DEBUG_HEALTH        (1 << 2)    // Debugging health calculations. 4
    DEBUG_DAMAGE        (1 << 3)    // Debugging OnTakeDamage hook. 8
    DEBUG_DATA          (1 << 4)    // Debugging data arrays. 16
    DEBUG_CRASHES       (1 << 5)    // Debugging crashes. NOTE: These are probably caused by an
                                    // outdated SM, so check the latest branch first. 32
    DEBUG_ZOMBIFY       (1 << 6)    // Debugging creation of zombies. 64
    DEBUG_RAGE          (1 << 7)    // Debugging zombie rage. 128
    DEBUG_HEALTHPACKS   (1 << 8)    // Debugging zombie health pack touches. 256
    DEBUG_ROUNDTIMER    (1 << 9)    // Debugging setting round/setup time. 512
    Some of these may or may not provide useful output or indeed function at all, as they were mainly for personal use when testing. Any output will be printed to the server console and log.

    tfbh_debug_flags - Debugging command to print all possible debug flag values to the server console.

    tfbh_debug_rage [Def. 0] - If 1, enables rage charging rate output to the HUD. You probably won't need this.

    tfbh_pushback_scale [Def. 2.0] - General multiplier for zombie pushback.

    tfbh_sentry_pushback_scale [Def. 0.5] - Multiplier for sentry pushback.

    tfbh_zhscale_min [Def. 1.0] - Minimum zombie health multiplier when against number of players specified in tfbh_zhscale_minplayercount (see below).

    tfbh_zhscale_minplayercount [Def. 1] - When player count is <= this value, zombies will be given minimum health.

    tfbh_zhscale_max [Def. 16.0] - Maximum zombie health multiplier when against number of players specified in tfbh_zhscale_maxplayercount (see below).

    tfbh_zhscale_maxplayercount [Def. 24] - When player count is >= this value, zombies will be given maximum health.

    tfbh_zombie_player_ratio [Def. 7] - At the beginning of a round, the number of zombies that spawn is (Red players/this value), rounded up. For example, with a team of 16 players and a ratio value of 7, ceil(16/7) = 3 players will become zombies.

    tfbh_zrespawn_min [Def. 1] - Minimum respawn time for zombies, when all survivors are alive.

    tfbh_zrespawn_max [Def. 6] - Maximum respawn time for zombies, when one survivor is left alive.

    tfbh_zrage_maxrate [Def. 6.0] - The max percentage rate at which a zombie's rage will charge every second when they are close to Red players.

    tfbh_zrage_minrate [Def. 0.5] - The min percentage rate at which a zombie's rage will charge every second when they are far from Red players.

    tfbh_zrage_close [Def. 128.0] - 'Close' distance to Red players, when zombie rage will charge fastest.

    tfbh_zrage_far [Def. 1024.0] - 'Far' distance to Red players, when zombie rage will charge slowest.

    tfbh_zrage_duration [Def. 3.0] - How long a zombie's rage lasts, in seconds.

    tfbh_zrage_radius [Def. 350] - The radius within which players and sentries will be stunned when a zombie rages.

    tfbh_zrage_stunduration [Def. 3] - Duration to stun players when a zombie rages.

    tfbh_always_zombify [Def. 1] - If 0, suicides will not make Red players turn into zombies. If 1, all deaths result in zombification.

    tfbh_superjump_force [Def. 800.0] - Upward force to apply when a zombie super-jumps, in units per second.

    tfbh_zrage_wetpenalty [Def. 2.0] - Penalty to apply per second to a zombie's rage when they are Jarate'd or milked.

    tfbh_zjarate_force [Def. 850] - Force with which to push players when a zombie Jarate jar explodes.

    tfbh_survivor_jarate_pushes [Def. 1] - Whether survivor Jarate also pushes zombies.

    tfbh_uber_added_on_hit [Def. 3.0] - How much uber a Medic is given per syringe hit.

    tfbh_uber_added_on_bolt [Def. 3.0] - How much uber a Medic is given per crossbow bolt hit.

    tfbh_setup_respawn_delay [Def. 0.5] - If >= 0, specified the delay after which a player who dies in setup will be respawned. If < 0, plugin does not force respawn (map might).

    tfbh_teleport_charge_per_sec [Def. 1.66] - How fast a zombie Engineer's teleport ability should charge, in points per second.

    tfbh_setup_time [Def. 60] - Amount of time players have to set up before the first person is infected.

    tfbh_round_time [Def. 300] - How long Red players must hold out to win.

    And that's pretty much it! I'm not sure how far this will go, but if anyone trials it up on a server then let me know and I'll pop by to check out the tests.

    Downloads:

    For the latest version of the plugin, see the attachments section of this post.

    Previous versions:
    GitHub code: https://github.com/x6herbius/tf2-biohazard

    Changelog
    Code:
    0.0.3.0:
     - Fixed a bug which allowed Blue zombies to join Red during a round.
    
    0.0.2.74 updated:
    - Recompiled to fix crash.
    
    0.0.2.74
    - Fixed damage from survivors not applying correctly.
    
    0.0.1.68
    - Fixed zombification not occurring.
    -- The DHooks extension is now no longer required for operation.
    -- SourceMod 1.7 is required instead.
    
    0.0.1.55
    - Setup/round time now controlled by tfbh_setup_time and tfbh_round_time respectively.
    - Some refactoring.
    
    0.0.0.1:
    - Initial version.
    Attached Files
    File Type: zip TFBiohazard_0.0.3.0.zip (38.2 KB, 179 views)

    Last edited by x6herbius; 03-31-2020 at 14:40.
    x6herbius is offline
    Send a message via Skype™ to x6herbius
    Oshizu
    Veteran Member
    Join Date: Nov 2012
    Location: Warsaw
    Old 04-20-2014 , 10:42   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #2

    Sounds promising
    Size of plugin is also quite big

    I guess i'il holdback with releasing my zombie tf gamemode for some time
    __________________
    ...

    Last edited by Oshizu; 04-20-2014 at 10:44.
    Oshizu is offline
    x6herbius
    Senior Member
    Join Date: May 2011
    Location: West Sussex, UK
    Old 04-20-2014 , 10:46   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #3

    It is a little monolithic. At some point I'd like to refactor things into separate files.
    x6herbius is offline
    Send a message via Skype™ to x6herbius
    Powerlord
    AlliedModders Donor
    Join Date: Jun 2008
    Location: Seduce Me!
    Old 04-20-2014 , 13:57   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #4

    Does this work with existing plugins zombie maps? (I've forgotten their prefix.)
    __________________
    Not currently working on SourceMod plugin development.
    Powerlord is offline
    x6herbius
    Senior Member
    Join Date: May 2011
    Location: West Sussex, UK
    Old 04-20-2014 , 14:30   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #5

    The zm_maps? I'm not sure. The critical things this mode needs to operate are A. the setup_finished hook (to choose the zombies), and B. some way to time out and have Red win. Other recommended things are disabling objectives so that they can't be capped and end the round early (I guess there's potential to incorporate objectives into gameplay somehow, but I haven't allowed for it as of yet) and providing multiple spawn areas for Blue players to help prevent spawn camping. From local testing I know that the Halloween Mountain Lab map works, as does Dustbowl (but the time left in the round is messed up a bit by the multiple stages - the round time doesn't reset to full once Red lose).
    x6herbius is offline
    Send a message via Skype™ to x6herbius
    Windroid
    Member
    Join Date: Mar 2013
    Old 04-21-2014 , 04:13   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #6

    i think the prepare time should be shorter,60 seconds is too long.
    if there's a cvar to set the prepare time should be better

    also,the round time is too long if there's only few player.they are hard to surrive.
    I think the round timer should be adjucted depends on the players number.

    and there's a bug,the botkiller weapon's robot head keep staying on screen in all class.

    Last edited by Windroid; 04-21-2014 at 08:33.
    Windroid is offline
    Powerlord
    AlliedModders Donor
    Join Date: Jun 2008
    Location: Seduce Me!
    Old 04-21-2014 , 14:42   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #7

    Speaking of the zombie skins thing that we were discussing over on Reddit... it might be possible to create new zombie models by taking the current class models and modifying them... then merging the zombie soul items into them (because part of the model is stored in them).

    I'm not sure how Valve would react to that, though. Then again, VSH uses a modded HHH model with a weapon attached to it and Valve didn't say anything about that...

    A few other things...

    Code:
    // This one's currently unknown (SM API page says Engineer building?)
    Slot 5 for Engineer is the tf_weapon_builder entity. This is the entity that actually constructs/destructs things (the Spy's stock Sapper is also a tf_weapon_builder, although the Red Tape Recorder is a tf_weapon_sapper instead). Both the Construction/Destruction tools and the build/destroy commands cause this to do things. In other words, destroying the Construction and Destruction tools will not stop an Engineer from building/destroying things via the console.

    I notice you're referencing a g_GameRules entity. As people have pointed out to me before, any time you store an entity index in a global variable, you should use EntIndexToEntRef on it first.

    However, since the GameRules entity should always exist, you could do something like this using SDKHooks:

    PHP Code:
    public OnEntityCreated(entity, const String:classname[])
    {
        if (
    StrEqual(classname"tf_gamerules"))
        {
            
    g_GameRules EntIndexToEntRef(entity);
        }

    This will save the gamerules entity any time it spawns.

    Note that you should use EntRefToEntIndex and check if the returned value is INVALID_ENT_REFERENCE to make sure the entity still exists before using it.

    Now, as for round timers... you can also create and/or manipulate the "team_round_timer" entity/entities on a map to change setup or round time. Most map modes have a single team_round_timer. KOTH has two. Arena has none by default unless tf_arena_round_time is greater than 0. PLR may or may not have one, but the only official map that has one doesn't end the round based on it (plr_nightfall). TC maps tend to have at least three (one for the middle rounds, two for the final rounds because they have different OnFinished conditions).

    Koth's two are a problem as they also appear on the HUD. You'll need to block the tf_logic_koth entity from spawning using SDKHooks, because it in in turn spawns the two timer entities. Then, you can create your own timer and do things as appropriate.

    You can add or modifying setup time to an existing team_round_timer in an SDKHook_Spawn Hook by using DispatchKeyValue on the "setup_length" property.

    If you need to see how to create a team_round_timer entity and what you need to set for it, you can see what PropHunt Redux does. PropHunt Redux spawns the team_round_timer when the team_control_point_master entity is spawned, which doesn't apply to game modes that don't use them (CTF mainly, but it's technically not required for TC and possibly KOTH).

    You can hook the OnFinished output via HookEntityOutput or HookSingleEntityOutput... that is assuming you want to call RoundWinWithCleanup rather than directly calling the team_control_point_master's SetWinner input (which is what PropHunt Redux does). Note that you may also want to HookSingleEntityOutput on its OnSetupFinished output just in case you run into buggy maps that have more than one timer running (ph_kakariko_a3 has this for PropHunt).

    Ugh, this has already run on too long.
    __________________
    Not currently working on SourceMod plugin development.

    Last edited by Powerlord; 04-21-2014 at 14:44.
    Powerlord is offline
    x6herbius
    Senior Member
    Join Date: May 2011
    Location: West Sussex, UK
    Old 04-21-2014 , 15:09   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #8

    Thanks for the info, that'll be really useful. I've tried doing things with team_round_timers this afternoon but I'm having trouble with the SetSetupTime and SetRoundTime inputs. Initially I was trying to find the team_round_timer in the round start hook and send the inputs, but for some reason, whatever I sent as the SetSetupTime value, the timer would always be set to 5 minutes of setup time and wouldn't respond to any ent_fire commands from the console. I then moved to hooking the OnSetupStart output from the timer in order to send the inputs (just in case the round start hook was too close to when the timer was reset), but it seems that the hook never gets fired. My ideal situation would be to remove any of the team_round_timers/game_round_wins/etc. present in the map and just have the plugin spawn its own to control all the round win logic - would the SDKHooks spawn hook be the best place to manage that?

    I'm also thinking of splitting this one monolithic plugin source file into multiple different ones just to help with refactoring and to preserve my sanity when it comes to editing. How does SourcePawn manage these things? I'm familiar with the C/C++ concept of including header files, and I can see that function prototypes are defined in .inc files for other plugins, but if you include a .inc does the compiler automatically discover the .sp file the function is implemented in?
    x6herbius is offline
    Send a message via Skype™ to x6herbius
    Powerlord
    AlliedModders Donor
    Join Date: Jun 2008
    Location: Seduce Me!
    Old 04-21-2014 , 17:00   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #9

    Quote:
    Originally Posted by x6herbius View Post
    Thanks for the info, that'll be really useful. I've tried doing things with team_round_timers this afternoon but I'm having trouble with the SetSetupTime and SetRoundTime inputs. Initially I was trying to find the team_round_timer in the round start hook and send the inputs, but for some reason, whatever I sent as the SetSetupTime value, the timer would always be set to 5 minutes of setup time and wouldn't respond to any ent_fire commands from the console.
    teamplay_round_start is probably too late to call SetSetupTime. I'm not sure why it would set it to 5 minutes, though, unless it was getting confused as to whether it's in setup or not (5 minutes is the round time on most pl and a/d cp maps).

    Quote:
    Originally Posted by x6herbius View Post
    I then moved to hooking the OnSetupStart output from the timer in order to send the inputs (just in case the round start hook was too close to when the timer was reset), but it seems that the hook never gets fired.
    OnSetupStart is definitely too late to change the setup time as if the timer doesn't already have setup time, it never gets called.

    Quote:
    Originally Posted by x6herbius View Post
    My ideal situation would be to remove any of the team_round_timers/game_round_wins/etc. present in the map and just have the plugin spawn its own to control all the round win logic - would the SDKHooks spawn hook be the best place to manage that?
    SDKHooks spawn hook is the perfect spot to block them. Since all entities spawned call them, including ones you create, you can check its m_iName property to make sure it's not equal to your timer's targetname. As I recall, returning Plugin_Stop will prevent the entity from spawning.

    However, I'm not sure if Waiting for Players creates its own team_round_timer. I think it does and I wrote a plugin to get the entity indexes and targetnames of all timers that exist, but I keep forgetting to actually upload said plugin and test it.

    Quote:
    Originally Posted by x6herbius View Post
    I'm also thinking of splitting this one monolithic plugin source file into multiple different ones just to help with refactoring and to preserve my sanity when it comes to editing. How does SourcePawn manage these things? I'm familiar with the C/C++ concept of including header files, and I can see that function prototypes are defined in .inc files for other plugins, but if you include a .inc does the compiler automatically discover the .sp file the function is implemented in?
    SourcePawn treats an #include as if you'd literally inserted the text of the file right where the #include is located. NativeVotes does this to break up its Data and Game-specific functions into separate files.

    The only catch is that static global variables and static functions are only visible inside the current file, much like static local variables are only visible in the current function. Actually, I need to go mark all my L4D, L4D2, TF2, and CSGO functions as static in NativeVotes to verify that my code is only calling the Game_ functions.
    __________________
    Not currently working on SourceMod plugin development.
    Powerlord is offline
    hkkelvin1995
    Senior Member
    Join Date: Jun 2009
    Location: Hong Kong
    Old 04-25-2014 , 11:06   Re: [TF2] Biohazard [0.0.0.1] [20/04/14]
    Reply With Quote #10

    After a day of testing
    My friends and I decided to host a server using your plugin
    We all think it is a potential mode
    You are bringing the thing we have wondered for years to Team Fortress
    It's very awesome, in fact, even it is now still in beta
    So I'm giving my feedback and suggestions here
    I hope this can help you to improve he plugin

    1. We have tested on some existing Zombie Fortress map (zf_). The plugin did work on most maps but not all.
    2. The preparation time seems depending on the map's settings so it will be good if there is gonna be a cvar can override he settings
    3. Please add a cvar that allows us to choose whether zombies are gonna in-place respawn. This would be useful on Escape map. You can take a took of Zombie Reloaded
    4. Replace spy's instant killing backstab with some negative effect to human
    5. Sniper's Huntsman seems can't be used

    So that's it for now
    I will post if I got any new idea or bug
    Have a nice day

    Last edited by hkkelvin1995; 04-25-2014 at 11:12.
    hkkelvin1995 is offline
    Reply



    Posting Rules
    You may not post new threads
    You may not post replies
    You may not post attachments
    You may not edit your posts

    BB code is On
    Smilies are On
    [IMG] code is On
    HTML code is Off

    Forum Jump


    All times are GMT -4. The time now is 01:24.


    Powered by vBulletin®
    Copyright ©2000 - 2024, vBulletin Solutions, Inc.
    Theme made by Freecode