muddy/
muddy/CVS/
muddy/area/
muddy/area/CVS/
muddy/clans/CVS/
muddy/classes/CVS/
muddy/doc/
muddy/doc/CVS/
muddy/etc/CVS/
muddy/etc/i3/
muddy/etc/i3/CVS/
muddy/imc/CVS/
muddy/lang/CVS/
muddy/licenses/CVS/
muddy/msgdb/CVS/
muddy/new/CVS/
muddy/notes/
muddy/player/
muddy/races/CVS/
muddy/religions/CVS/
muddy/src/CVS/
muddy/src/comm/CVS/
muddy/src/db/CVS/
muddy/src/intermud/
muddy/src/intermud/CVS/
muddy/src/irc/CVS/
muddy/src/olc/CVS/
/* $Id: olc_race.c,v 1.666 2004/09/20 10:50:30 shrike Exp $ */

/************************************************************************************
 *    Copyright 2004 Astrum Metaphora consortium                                    *
 *                                                                                  *
 *    Licensed under the Apache License, Version 2.0 (the "License");               *
 *    you may not use this file except in compliance with the License.              *
 *    You may obtain a copy of the License at                                       *
 *                                                                                  *
 *    http://www.apache.org/licenses/LICENSE-2.0                                    *
 *                                                                                  *
 *    Unless required by applicable law or agreed to in writing, software           *
 *    distributed under the License is distributed on an "AS IS" BASIS,             *
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.      *
 *    See the License for the specific language governing permissions and           *
 *    limitations under the License.                                                *
 *                                                                                  *
 ************************************************************************************/
 
#include <stdio.h>
#include <stdlib.h>

#include "merc.h"
#include "olc.h"

#define EDIT_RACE(ch, race) (race = (race_t*) ch->desc->pEdit)

DECLARE_OLC_FUN(raceed_create   );
DECLARE_OLC_FUN(raceed_edit     );
DECLARE_OLC_FUN(raceed_touch    );
DECLARE_OLC_FUN(raceed_show     );
DECLARE_OLC_FUN(raceed_list     );

DECLARE_OLC_FUN(raceed_name     );
DECLARE_OLC_FUN(raceed_filename );
DECLARE_OLC_FUN(raceed_flags    );
DECLARE_OLC_FUN(raceed_parts    );
DECLARE_OLC_FUN(raceed_act      );
DECLARE_OLC_FUN(raceed_off      );
DECLARE_OLC_FUN(raceed_aff      );
DECLARE_OLC_FUN(raceed_form     );
DECLARE_OLC_FUN(raceed_immune   );
DECLARE_OLC_FUN(raceed_resist   );
DECLARE_OLC_FUN(raceed_dodge    );

DECLARE_OLC_FUN(raceed_spec_part);
DECLARE_OLC_FUN(raceed_love_sect);
DECLARE_OLC_FUN(raceed_hate_sect);

DECLARE_OLC_FUN(pcraceed_create);
DECLARE_OLC_FUN(pcraceed_skill    );

DECLARE_OLC_FUN(pcraceed_skill_add);
DECLARE_OLC_FUN(pcraceed_skill_del);

static DECLARE_VALIDATE_FUN(validate_name  );
static DECLARE_VALIDATE_FUN(validate_haspcdata  );

static bool touch_race(race_t *r);

olc_cmd_t olc_cmds_race[] =
{
    { "create",     raceed_create,   5                    },
    { "edit",       raceed_edit,     5                    },
    { "touch",      raceed_touch,    5                    },
    { "show",       raceed_show,     0                    },
    { "list",       raceed_list,     0                    },

    { "name",       raceed_name,     5, validate_name     },
    { "filename",   raceed_filename, 5, validate_filename },
    { "dodge",      raceed_dodge,    5,                   },
    { "spec_part",  raceed_spec_part,5,                   },
    { "love_sect",  raceed_love_sect,5, sector_flag_types },
    { "hate_sect",  raceed_hate_sect,5, sector_flag_types },
    { "form",       raceed_form,     0, form_flags        },
    { "part",       raceed_parts,    5, part_flags        },
    { "imm",        raceed_immune,   5, imm_flags         },
    { "res",        raceed_resist,   5, dam_flags         },
    { "off",        raceed_off,      5, off_flags         },
    { "act",        raceed_act,      5, act_flags         },
    { "affect",     raceed_aff,      5, affect_flags      },

    { "pcrace",     pcraceed_create, 5                    },
    { "skill",      pcraceed_skill,  0, validate_haspcdata},

    { "commands",   show_commands,   0                    },
    { NULL}
};

OLC_FUN(raceed_create)
{
    int rn;
    race_t *race;

    if (ch->pcdata->security < SECURITY_RACES)
    {
        char_puts("RaceEd: Insufficient security for editing races\n", ch);
        return FALSE;
    }

    if (argument[0] == '\0')
    {
        do_help(ch, "'OLC CREATE'");
        return FALSE;
    }

    if ((rn = rn_lookup(argument)) >= 0)
    {
        char_printf(ch, "RaceEd: %s: already exists.\n", RACE(rn)->name);
        return FALSE;
    }

    race            = race_new();
    race->name      = str_dup(argument);
    race->file_name = str_printf("race%02d.race", races.nused-1);

    ch->desc->pEdit     = (void *)race;
    OLCED(ch)   = olced_lookup(ED_RACE);
    touch_race(race);
    char_puts("Race created.\n",ch);
    return FALSE;
}

OLC_FUN(raceed_edit)
{
    int rn;
    char arg[MAX_STRING_LENGTH];

        if (ch->pcdata->security < SECURITY_RACES)
    {
        char_puts("RaceEd: Insufficient security.\n", ch);
        return FALSE;
    }
    one_argument(argument, arg, sizeof(arg));
    if (arg[0] == '\0')
    {
        do_help(ch, "'OLC EDIT'");
        return FALSE;
    }
    if ((rn = rn_lookup(arg)) < 0)
    {
        char_printf(ch, "RaceEd: %s: No such race.\n", argument);
        return FALSE;
    }
    ch->desc->pEdit     = RACE(rn);
    OLCED(ch)   = olced_lookup(ED_RACE);
    return FALSE;
}

OLC_FUN(raceed_touch)
{
    race_t *race;
    EDIT_RACE(ch, race);
    return touch_race(race);
}


OLC_FUN(raceed_dodge)
{
    race_t *race;
    EDIT_RACE(ch, race);
    
    return olced_number(ch, argument, cmd, &race->dodge);
}

OLC_FUN(raceed_parts    )
{
    race_t *race;
    EDIT_RACE(ch, race);

    return olced_flag64(ch, argument, cmd, &race->parts);
}

OLC_FUN(raceed_act      )
{
    race_t *race;
    EDIT_RACE(ch, race);

    return olced_flag64(ch, argument, cmd, &race->act);
}

OLC_FUN(raceed_off      )
{
    race_t *race;
    EDIT_RACE(ch, race);

    return olced_flag64(ch, argument, cmd, &race->off);
}

OLC_FUN(raceed_aff      )
{
    race_t *race;
    EDIT_RACE(ch, race);

    return olced_flag64(ch, argument, cmd, &race->aff);
}

OLC_FUN(raceed_form     )
{
    race_t *race;
    EDIT_RACE(ch, race);

    return olced_flag64(ch, argument, cmd, &race->form);
}

OLC_FUN(raceed_immune   )
{
    race_t *race;
    EDIT_RACE(ch, race);

    return olced_flag64(ch, argument, cmd, &race->immunes);
}

OLC_FUN(raceed_resist   )
{
    race_t *race;
    int dam_type;
    char arg[MAX_INPUT_LENGTH];
    
    EDIT_RACE(ch, race);
    argument = one_argument(argument, arg, MAX_INPUT_LENGTH);
    
    if (olced_flag32(ch, arg, cmd, &dam_type) && is_number(argument))
    {
		race->resists[dam_type] = atoi(argument);
		return TRUE;
    }
    
    return FALSE;
}

OLC_FUN(raceed_show)
{
    char arg[MAX_STRING_LENGTH];
    int i;
    BUFFER *output;
    race_t *race;
    pcrace_t *pcr;

    one_argument(argument, arg, sizeof(arg));
    if (arg[0] == '\0')
    {
        if (IS_EDIT(ch, ED_RACE))
            EDIT_RACE(ch, race);
        else
        {
            do_help(ch, "'OLC ASHOW'");
            return FALSE;
        }
    }
    else
    {
        if ((i = rn_lookup(arg)) < 0)
        {
            char_printf(ch, "RaceEd: %s: No such race.\n",  argument);
            return FALSE;
        }
        race = RACE(i);
    }
    output = buf_new(ch->lang);
    buf_printf(output,
               "Name:          [%s]\n"
               "Filename:      [%s]\n"
               "Dodge:         [%d]\n",
               race->name,
               race->file_name,
               race->dodge);

    if (race->flags)
        buf_printf(output, "Flags:         [%s]\n",    flag_string(race_flags, race->flags));

    buf_printf (output, "Loves sectors: [%s]\n", flag_string(sector_flag_types, race->loved_sectors));
    buf_printf (output, "Hates sectors: [%s]\n", flag_string(sector_flag_types, race->hated_sectors));

    if (race->act)
        buf_printf(output, "Act:           [%s]\n",    flag_string(act_flags, race->act));
    if (race->off)
        buf_printf(output, "Off:           [%s]\n",    flag_string(off_flags, race->off));
    if (race->parts)
        buf_printf(output, "Body parts:    [%s]\n",    flag_string(part_flags, race->parts));
    if (race->aff)
        buf_printf(output, "Aff:           [%s]\n",    flag_string(affect_flags, race->aff));

    if (race->immunes)
    buf_printf(output, "Immunes:       [%s]\n",    flag_string(imm_flags, race->immunes));
    
    
    for (i = 0; i < MAX_DAM; i++)
        if (race->resists[i])
            buf_printf(output, "Res:           [%-16.16s:%4d%%]\n", flag_string(dam_flags, i), race->resists[i]);
    
    for (i = 0; i < MAX_SPEC_PARTS; ++i)
        if (race->spec_parts[i] != 0)
            break;

    if (i < MAX_SPEC_PARTS)
    {
        OBJ_INDEX_DATA * obj;

        buf_add (output, "Special parts:\n");
        buf_add (output, "{x    Min. level Probability Object        :\n");
        for (i = 0; i < MAX_SPEC_PARTS; ++i)
        {
            obj = get_obj_index (race->spec_parts[i]);
            buf_printf (output, "{G%2d{x.   [%3d]       [%4d]   [%7d] %s\n", 
                i + 1,
                race->spec_levels[i],
                race->spec_prob[i],
                race->spec_parts[i], 
                obj == NULL ? "non-existent object" : mlstr_cval (obj->short_descr, ch));
        }
    }
    if ((pcr = race->pcdata))
    {
        buf_printf(output, "\n{WPC data:{x\n\n");
        if (pcr->flags)
                buf_printf(output, "Flags:        [%s]\n",  flag_string(race_flags, pcr->flags));
        buf_printf(output, "ShortName:    [%s]\n", pcr->who_name);
        buf_printf(output, "Points:       [%d]\n", pcr->points);
        for (i = 0; i < pcr->classes.nused; i++) 
        {
             rclass_t *race_class = VARR_GET(&pcr->classes, i);
             int cn;

             if ((cn = cn_lookup(race_class->name)) < 0)
                        continue;
             buf_printf(output, "Class:        '%s' (mult %d)\n", CLASS(cn)->name, race_class->mult);
        }
        
        if (pcr->bonus_skills)
                buf_printf(output, "BonusSkills   [%s]\n", pcr->bonus_skills);
        
        for (i = 0; i < pcr->skills.nused; i++) 
        {
             race_skill_t *race_skill = VARR_GET(&pcr->skills, i);
             skill_t *skill;

             if (race_skill->sn <= 0  || (skill = skill_lookup(race_skill->sn)) == NULL)
             continue;
             buf_printf(output, "Skill:       '%s' (level %d)\n",
             
             skill->name, race_skill->level);
        }
        
        buf_printf(output, "Stats        ");
        for (i = 0; i < MAX_STATS; i++)         buf_printf(output, " %d", pcr->stats[i]);
        buf_printf(output, "\n");
        buf_printf(output, "MaxStats     ");
        for (i = 0; i < MAX_STATS; i++)         buf_printf(output, " %d", pcr->max_stats[i]);
        buf_printf(output, "\n");
                                   buf_printf(output, "Size:         [%d]\n", pcr->size);
        if (pcr->hp_bonus)         buf_printf(output, "HPBonus:      [%d]\n", pcr->hp_bonus);
        if (pcr->mana_bonus)       buf_printf(output, "ManaBonus:    [%d]\n", pcr->mana_bonus);
        if (pcr->prac_bonus)       buf_printf(output, "PracBonus:    [%d]\n", pcr->prac_bonus);
        if (pcr->restrict_align)   buf_printf(output, "RestrictAlign [%s]\n", flag_string(ralign_names, pcr->restrict_align));
        if (pcr->restrict_ethos)   buf_printf(output, "RestrictEthos [%s]\n", flag_string(ethos_table, pcr->restrict_ethos));
        if (pcr->restrict_sex)     buf_printf(output, "RestrictSex   [%s]\n", flag_string(restrict_sex_table, pcr->restrict_sex));
                                   buf_printf(output, "Slang         [%s]", flag_string(slang_table, pcr->slang));
    }

    buf_printf(output, "\n\r");
    page_to_char(buf_string(output), ch);
    buf_free(output);

    return FALSE;
}

OLC_FUN(raceed_list)
{
    int i;
    for (i = 0; i < races.nused; i++)
        char_printf(ch, "[%d] %s\n", i, RACE(i)->name);
    return FALSE;
}

OLC_FUN(raceed_name)
{
    race_t *race;
    EDIT_RACE(ch, race);
    return olced_str(ch, argument, cmd, &race->name);
}

OLC_FUN(raceed_filename)
{
    race_t *race;
    EDIT_RACE(ch, race);
    return olced_str(ch, argument, cmd, &race->file_name);
}

OLC_FUN(raceed_flags)
{
    race_t *race;
    EDIT_RACE(ch, race);
    return olced_flag64(ch, argument, cmd, &race->flags);
}

OLC_FUN(raceed_love_sect)
{
    race_t *race;
    EDIT_RACE(ch, race);
    return olced_flag64(ch, argument, cmd, &race->loved_sectors);
}

OLC_FUN(raceed_hate_sect)
{
    race_t *race;
    EDIT_RACE(ch, race);
    return olced_flag64(ch, argument, cmd, &race->hated_sectors);
}

OLC_FUN(raceed_spec_part)
{
    race_t *race;
    char arg[MAX_STRING_LENGTH];
    int num, vnum, prob, level;

    EDIT_RACE(ch, race);

    // number
    argument = one_argument (argument, arg, sizeof(arg));
    num = atoi (arg);
    if (num < 1 || num > MAX_SPEC_PARTS)
    {
        char_act ("Syntax: spec_part <num> <vnum> <probability> <min_level>", ch);
        char_printf (ch, "Num must be between 1 and %d.\n", MAX_SPEC_PARTS);
        return FALSE;
    }

    // vnum 
    argument = one_argument (argument, arg, sizeof(arg));
    vnum = atoi (arg);
    vnum = UMAX (0, vnum);
    // validate vnum
    if (vnum != 0 && get_obj_index (vnum) == NULL)
    {
        char_printf (ch, "Obj vnum %d does not exist.\n", vnum);
        return FALSE;
    }

    // probability
    argument = one_argument (argument, arg, sizeof(arg));
    prob = atoi (arg);
    prob = UMAX (0, prob);
    if (prob > MAX_SPEC_PROB)
    {
        char_act ("Syntax: spec_part <num> <vnum> <probability> <min_level>", ch);
        char_printf (ch, "Probability must be between 0 and %d.\n", MAX_SPEC_PROB);
        return FALSE;
    }

    // level
    argument = one_argument (argument, arg, sizeof(arg));
    level = atoi (arg);
    level = UMAX (0, level);

    // fill the arrays
    race->spec_prob[num - 1] = prob;
    race->spec_parts[num - 1] = vnum;
    race->spec_levels[num - 1] = level;
    char_act ("Ok.", ch);
    return TRUE;
}

OLC_FUN(pcraceed_create)
{
        race_t *race;
        EDIT_RACE(ch, race);
        if (race->pcdata != NULL)
        {
                char_printf(ch, "RaceEd: %s: pcrace already exists.\n", race->name);
                return FALSE;
        }
        race->pcdata = race_pcdata_new();
        return TRUE;
}

OLC_FUN(pcraceed_skill)
{
    char arg[MAX_STRING_LENGTH];
    argument = one_argument(argument, arg, sizeof(arg));
    if (!str_prefix(arg, "add"))
        return pcraceed_skill_add(ch, argument, cmd);
    else if (!str_prefix(arg, "delete"))
        return pcraceed_skill_del(ch, argument, cmd);
    do_help(ch, "'OLC RACE SKILL'");
    return FALSE;
}

OLC_FUN(pcraceed_skill_add)
{
    int sn;
    race_skill_t *race_skill;
    char    arg1[MAX_STRING_LENGTH];
    char    arg2[MAX_STRING_LENGTH];
    race_t *race;
    EDIT_RACE(ch, race);
    argument = one_argument(argument, arg1, sizeof(arg1));
    argument = one_argument(argument, arg2, sizeof(arg2));
    if (arg1[0] == '\0' || arg2[0] == '\0')
    {
        do_help(ch, "'OLC RACE SKILL'");
        return FALSE;
    }
    if ((sn = sn_lookup(arg1)) <= 0)
    {
        char_printf(ch, "RaceEd: %s: unknown skill.\n", arg1);
        return FALSE;
    }

    if ((race_skill = race_skill_lookup(race, sn)))
    {
        char_printf(ch, "RaceEd: %s: already there.\n",
                    SKILL(sn)->name);
        return FALSE;
    }

    race_skill = varr_enew(&race->pcdata->skills);
    race_skill->sn = sn;
    race_skill->level = atoi(arg2);
    varr_qsort(&race->pcdata->skills, cmpint);

    return TRUE;
}

OLC_FUN(pcraceed_skill_del)
{
    char    arg[MAX_STRING_LENGTH];
    race_skill_t *race_skill;
    race_t *race;
    EDIT_RACE(ch, race);
    one_argument(argument, arg, sizeof(arg));
    if ((race_skill = skill_vlookup(&race->pcdata->skills, arg)) == NULL)
    {
        char_printf(ch, "RaceEd: %s: not found in pcrace skill list.\n", arg);
        return FALSE;
    }
    race_skill->sn = 0;
    varr_qsort(&race->pcdata->skills, cmpint);
    return TRUE;
}

static VALIDATE_FUN(validate_name)
{
    int i;
    race_t *race;
    EDIT_RACE(ch, race);

    for (i = 0; i < races.nused; i++)
        if (RACE(i) != race  &&  !str_cmp(RACE(i)->name, arg))
        {
            char_printf(ch, "RaceEd: %s: duplicate race name.\n", arg);
            return FALSE;
        }
    return TRUE;
}

static VALIDATE_FUN(validate_haspcdata)
{
        race_t *race;
        EDIT_RACE(ch, race);
        if (race->pcdata == NULL)
        {
                char_printf(ch, "RaceEd: %s: no race pcdata.\n", race->name);
                return FALSE;
        }
        return TRUE;
}

static bool touch_race(race_t *race)
{
    SET_BIT(race->flags, RACE_CHANGED);
    return FALSE;
}