/* $Id: olc_race.c 849 2006-04-22 13:08:54Z zsuzsu $ */
/************************************************************************************
* 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_vulnerable );
DECLARE_OLC_FUN(raceed_size );
DECLARE_OLC_FUN(raceed_sex );
DECLARE_OLC_FUN(raceed_ac );
DECLARE_OLC_FUN(raceed_dodge );
DECLARE_OLC_FUN(raceed_damtype );
DECLARE_OLC_FUN(raceed_align );
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_age );
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[] =
{
{ 5, "create", raceed_create, },
{ 5, "edit", raceed_edit, },
{ 5, "touch", raceed_touch, },
{ 0, "show", raceed_show, },
{ 0, "list", raceed_list, },
{ 5, "name", raceed_name, validate_name },
{ 5, "filename", raceed_filename, validate_filename },
{ 5, "align", raceed_align, },
{ 5, "sex", raceed_sex, sex_table },
{ 5, "size", raceed_size, size_table },
/*
{ 5, "ac", raceed_armor, armor_table },
{ 5, "armor", raceed_armor, armor_table },
*/
{ 5, "dodge", raceed_dodge, },
{ 5, "damtype", raceed_damtype, },
/*
{ 5, "spec_part", raceed_spec_part,5, },
{ 5, "love_sect", raceed_love_sect,5, sector_flag_types },
{ 5, "hate_sect", raceed_hate_sect,5, sector_flag_types },
*/
{ 5, "form", raceed_form, form_flags },
{ 5, "part", raceed_parts, part_flags },
{ 5, "imm", raceed_immune, imm_flags },
{ 5, "res", raceed_resist, imm_flags },
{ 5, "vuln", raceed_vulnerable, imm_flags },
{ 5, "off", raceed_off, off_flags },
{ 5, "act", raceed_act, act_flags },
{ 5, "affect", raceed_aff, affect_flags },
/* { 9, "pcrace", pcraceed_create, },
{ 8, "age", pcraceed_age, },
{ 5, "skill", pcraceed_skill, validate_haspcdata },
*/
{ 0, "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_flag32(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_flag32(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_flag32(ch, argument, cmd, &race->form);
}
OLC_FUN(raceed_immune )
{
race_t *race;
EDIT_RACE(ch, race);
return olced_flag32(ch, argument, cmd, &race->imm);
}
OLC_FUN(raceed_resist )
{
race_t *race;
EDIT_RACE(ch, race);
return olced_flag32(ch, argument, cmd, &race->res);
}
OLC_FUN(raceed_vulnerable )
{
race_t *race;
EDIT_RACE(ch, race);
return olced_flag32(ch, argument, cmd, &race->vuln);
}
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", race->name);
buf_printf(output, "Filename: [%s]\n", race->file_name);
buf_printf(output, "Align: [%4d]\n",race->alignment);
buf_printf(output, "Sex: [%s]\n", flag_string(sex_table, race->sex));
buf_printf(output, "Size: [%s]\n", flag_string(size_table, race->size));
buf_printf(output, "Dodge Skill: [%d] (NPC only)\n", race->dodge);
buf_printf(output, "DamType: [%s]\n", attack_table[race->dam_type].name);
buf_printf(output, "Act: [%s]\n", flag_string(act_flags, race->act));
buf_printf(output, "Aff: [%s]\n", flag_string(affect_flags, race->aff));
buf_printf(output, "Off: [%s]\n", flag_string(off_flags, race->off));
buf_printf(output, "Immune: [%s]\n", flag_string(imm_flags, race->imm));
buf_printf(output, "Resists: [%s]\n", flag_string(imm_flags, race->res));
buf_printf(output, "Vuln: [%s]\n", flag_string(imm_flags, race->vuln));
buf_printf(output, "Body parts: [%s]\n", flag_string(part_flags, race->parts));
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));
*/
/*
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");
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);
}
buf_printf(output, "BonusSkills [%s]\n", pcr->bonus_skills);
for (i = 0; i < pcr->skills.nused; i++)
{
rskill_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: [%s]\n", flag_string(size_table, pcr->size));
buf_printf(output, "HPBonus: [%d]\n", pcr->hp_bonus);
buf_printf(output, "ManaBonus: [%d]\n", pcr->mana_bonus);
buf_printf(output, "PracBonus: [%d]\n", pcr->prac_bonus);
buf_printf(output, "RestrictAlign [%s]\n", flag_string(ralign_names, pcr->restrict_align));
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]\n", flag_string(slang_table, pcr->slang));
buf_printf(output, "Flags: [%s]", flag_string(race_flags, pcr->flags));
}
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_flag32(ch, argument, cmd, &race->flags);
}
OLC_FUN(raceed_damtype)
{
char arg[MAX_INPUT_LENGTH];
int dt;
race_t *race;
EDIT_RACE(ch, race);
one_argument(argument, arg, sizeof(arg));
if (arg[0] == '\0') {
char_puts("Syntax: damtype [damage message]\n", ch);
char_puts("Syntax: damtype ?\n", ch);
return FALSE;
}
if (!str_cmp(arg, "?")) {
BUFFER *output = buf_new(-1);
show_attack_types(output);
page_to_char(buf_string(output), ch);
buf_free(output);
return FALSE;
}
if ((dt = attack_lookup(arg)) < 0) {
char_printf(ch, "RaceEd: %s: unknown damtype.\n", arg);
return FALSE;
}
race->dam_type = dt;
char_puts("Damage type set.\n", ch);
return TRUE;
}
OLC_FUN(raceed_align)
{
race_t *race;
EDIT_RACE(ch, race);
return olced_number(ch, argument, cmd, &race->alignment);
}
OLC_FUN(raceed_sex)
{
race_t *race;
EDIT_RACE(ch, race);
return olced_flag32(ch, argument, cmd, &race->sex);
}
OLC_FUN(raceed_size)
{
race_t *race;
EDIT_RACE(ch, race);
return olced_flag32(ch, argument, cmd, &race->size);
}
/*
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 = pcrace_new();
return TRUE;
}
OLC_FUN(pcraceed_age)
{
race_t *race;
EDIT_RACE(ch, race);
if (race->pcdata != NULL)
{
char_printf(ch, "RaceEd: %s: isn't a PC race.\n", race->name);
return FALSE;
}
return olced_number(ch, argument, cmd, &race->pcdata->age_modifier);
}
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;
rskill_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 = rskill_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];
rskill_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;
}