2015-07-06 19:53:09 +02:00
/*
2015-01-30 22:10:29 +01:00
Copyright ( c ) 1998 - 2015 , Enno Rehling < enno @ eressea . de >
2014-08-23 09:17:58 +02:00
Katja Zedel < katze @ felidae . kn - bremen . de
Christian Schlittchen < corwin @ amber . kn - bremen . de >
2010-08-08 10:06:34 +02:00
Permission to use , copy , modify , and / or distribute this software for any
purpose with or without fee is hereby granted , provided that the above
copyright notice and this permission notice appear in all copies .
THE SOFTWARE IS PROVIDED " AS IS " AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS . IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT , INDIRECT , OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
* */
# include <platform.h>
# include <kernel/config.h>
# include "item.h"
# include <attributes/key.h>
# include "alchemy.h"
# include "build.h"
2012-06-03 21:51:35 +02:00
# include "curse.h"
2010-08-08 10:06:34 +02:00
# include "faction.h"
2014-06-09 18:54:48 +02:00
# include "messages.h"
2010-08-08 10:06:34 +02:00
# include "pool.h"
# include "race.h"
# include "region.h"
# include "save.h"
# include "skill.h"
# include "terrain.h"
# include "unit.h"
/* triggers includes */
# include <triggers/changerace.h>
# include <triggers/timeout.h>
/* util includes */
# include <util/attrib.h>
# include <util/base36.h>
2012-05-31 04:43:11 +02:00
# include <critbit.h>
2010-08-08 10:06:34 +02:00
# include <util/event.h>
# include <util/functions.h>
# include <util/goodies.h>
2010-08-15 04:41:18 +02:00
# include <util/log.h>
2010-08-08 10:06:34 +02:00
# include <util/language.h>
# include <util/message.h>
# include <util/umlaut.h>
# include <util/rng.h>
/* libc includes */
# include <assert.h>
# include <stdlib.h>
# include <string.h>
2012-05-21 22:18:05 +02:00
static critbit_tree inames [ MAXLOCALES ] ;
2012-05-23 07:01:48 +02:00
static critbit_tree rnames [ MAXLOCALES ] ;
2012-05-19 20:26:46 +02:00
static critbit_tree cb_resources ;
2011-03-07 08:02:35 +01:00
luxury_type * luxurytypes ;
potion_type * potiontypes ;
2010-08-08 10:06:34 +02:00
2011-03-07 08:02:35 +01:00
static int res_changeaura ( unit * u , const resource_type * rtype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( rtype ! = NULL ) ;
return change_spellpoints ( u , delta ) ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static int res_changeperson ( unit * u , const resource_type * rtype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( rtype ! = NULL | | ! " not implemented " ) ;
if ( u - > number + delta > = 0 ) {
scale_number ( u , u - > number + delta ) ;
}
else {
scale_number ( u , 0 ) ;
}
return u - > number ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static int res_changepermaura ( unit * u , const resource_type * rtype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( rtype ! = NULL ) ;
return change_maxspellpoints ( u , delta ) ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static int res_changehp ( unit * u , const resource_type * rtype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( rtype ! = NULL ) ;
u - > hp + = delta ;
return u - > hp ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static int res_changepeasants ( unit * u , const resource_type * rtype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( rtype ! = NULL & & u - > region - > land ) ;
u - > region - > land - > peasants + = delta ;
return u - > region - > land - > peasants ;
2010-08-08 10:06:34 +02:00
}
2014-08-24 17:09:32 +02:00
static int golem_factor ( const unit * u , const resource_type * rtype ) {
if ( rtype = = get_resourcetype ( R_STONE ) & & ( u_race ( u ) - > flags & RCF_STONEGOLEM ) ) {
return GOLEM_STONE ;
}
if ( rtype = = get_resourcetype ( R_IRON ) & & ( u_race ( u ) - > flags & RCF_IRONGOLEM ) ) {
return GOLEM_IRON ;
}
return 0 ;
}
2012-05-26 01:15:21 +02:00
static int res_changeitem ( unit * u , const resource_type * rtype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
int num ;
2015-01-30 20:37:14 +01:00
int gf = ( delta > 0 ) ? 0 : golem_factor ( u , rtype ) ;
if ( gf > 0 ) {
2014-08-24 17:09:32 +02:00
if ( delta ! = 0 ) {
int reduce = delta / gf ;
if ( delta % gf ! = 0 ) {
- - reduce ;
}
if ( reduce ) scale_number ( u , u - > number + reduce ) ;
}
num = u - > number * gf ;
2014-08-23 09:17:58 +02:00
}
else {
const item_type * itype = resource2item ( rtype ) ;
item * i ;
assert ( itype ! = NULL ) ;
i = i_change ( & u - > items , itype , delta ) ;
if ( i = = NULL )
return 0 ;
num = i - > number ;
}
return num ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
const char * resourcename ( const resource_type * rtype , int flags )
2010-08-08 10:06:34 +02:00
{
2014-08-24 22:30:35 +02:00
if ( ! rtype )
2015-01-30 20:37:14 +01:00
assert ( rtype ) ;
2014-08-23 09:17:58 +02:00
if ( rtype ) {
if ( rtype - > name )
return rtype - > name ( rtype , flags ) ;
2010-08-08 10:06:34 +02:00
2014-08-24 22:30:35 +02:00
if ( flags & NMF_APPEARANCE & & rtype - > itype ) {
int i = ( flags & NMF_PLURAL ) ? 1 : 0 ;
const char * result = rtype - > itype - > _appearance [ i ] ;
if ( result ) {
return result ;
}
}
if ( flags & NMF_PLURAL ) {
static char name [ 64 ] ; // FIXME: static return value
_snprintf ( name , sizeof ( name ) , " %s_p " , rtype - > _name ) ;
return name ;
2014-08-23 09:17:58 +02:00
}
2014-08-24 22:30:35 +02:00
return rtype - > _name ;
2010-08-08 10:06:34 +02:00
}
2014-08-23 09:17:58 +02:00
return " none " ;
2010-08-08 10:06:34 +02:00
}
2014-06-30 02:02:45 +02:00
static int num_resources ;
static void rt_register ( resource_type * rtype )
{
char buffer [ 64 ] ;
2014-08-24 22:30:35 +02:00
const char * name = rtype - > _name ;
2014-06-30 02:02:45 +02:00
size_t len = strlen ( name ) ;
2014-08-23 09:17:58 +02:00
assert ( len < sizeof ( buffer ) - sizeof ( rtype ) ) ;
2014-06-30 02:02:45 +02:00
len = cb_new_kv ( name , len , & rtype , sizeof ( rtype ) , buffer ) ;
cb_insert ( & cb_resources , buffer , len ) ;
+ + num_resources ;
}
2014-06-25 07:44:05 +02:00
resource_type * rt_get_or_create ( const char * name ) {
resource_type * rtype = rt_find ( name ) ;
if ( ! rtype ) {
rtype = ( resource_type * ) calloc ( sizeof ( resource_type ) , 1 ) ;
2014-08-24 22:30:35 +02:00
rtype - > _name = _strdup ( name ) ;
2014-06-25 07:44:05 +02:00
rt_register ( rtype ) ;
}
return rtype ;
}
2014-10-14 18:32:04 +02:00
static void it_register ( item_type * itype )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
char buffer [ 64 ] ;
2014-08-24 22:30:35 +02:00
const char * name = itype - > rtype - > _name ;
2014-08-23 09:17:58 +02:00
size_t len = strlen ( name ) ;
2012-05-19 20:26:46 +02:00
2014-08-23 09:17:58 +02:00
assert ( len < sizeof ( buffer ) - sizeof ( itype ) ) ;
len = cb_new_kv ( name , len , & itype , sizeof ( itype ) , buffer ) ;
2010-08-08 10:06:34 +02:00
}
2014-06-25 07:44:05 +02:00
static const char * it_aliases [ ] [ 2 ] = {
2015-01-30 20:37:14 +01:00
{ " Runenschwert " , " runesword " } ,
{ " p12 " , " truthpotion " } ,
{ " p1 " , " goliathwater " } ,
{ " p4 " , " ointment " } ,
{ " p5 " , " peasantblood " } ,
{ " p8 " , " nestwarmth " } ,
{ " diamond " , " adamantium " } ,
{ " diamondaxe " , " adamantiumaxe " } ,
{ " diamondplate " , " adamantiumplate " } ,
{ " aoh " , " ao_healing " } ,
{ NULL , NULL } ,
2014-06-25 07:44:05 +02:00
} ;
static const char * it_alias ( const char * zname )
{
2014-08-23 09:17:58 +02:00
int i ;
for ( i = 0 ; it_aliases [ i ] [ 0 ] ; + + i ) {
if ( strcmp ( it_aliases [ i ] [ 0 ] , zname ) = = 0 )
return it_aliases [ i ] [ 1 ] ;
}
return zname ;
2014-06-25 07:44:05 +02:00
}
item_type * it_find ( const char * zname )
{
const char * name = it_alias ( zname ) ;
resource_type * result = rt_find ( name ) ;
return result ? result - > itype : 0 ;
}
item_type * it_get_or_create ( resource_type * rtype ) {
item_type * itype ;
assert ( rtype ) ;
2014-08-24 22:30:35 +02:00
itype = it_find ( rtype - > _name ) ;
2014-06-30 02:02:45 +02:00
assert ( ! itype | | ! itype - > rtype | | itype - > rtype = = rtype ) ;
if ( ! itype ) {
itype = ( item_type * ) calloc ( sizeof ( item_type ) , 1 ) ;
}
2014-06-25 07:44:05 +02:00
itype - > rtype = rtype ;
2014-06-30 02:02:45 +02:00
rtype - > uchange = res_changeitem ;
rtype - > itype = itype ;
2014-06-25 07:44:05 +02:00
rtype - > flags | = RTF_ITEM ;
it_register ( itype ) ;
return itype ;
}
2011-03-07 08:02:35 +01:00
static void lt_register ( luxury_type * ltype )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
ltype - > itype - > rtype - > ltype = ltype ;
ltype - > next = luxurytypes ;
luxurytypes = ltype ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
luxury_type * new_luxurytype ( item_type * itype , int price )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
luxury_type * ltype ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
assert ( resource2luxury ( itype - > rtype ) = = NULL ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
ltype = calloc ( sizeof ( luxury_type ) , 1 ) ;
ltype - > itype = itype ;
ltype - > price = price ;
lt_register ( ltype ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
return ltype ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
weapon_type * new_weapontype ( item_type * itype ,
2014-08-23 09:17:58 +02:00
int wflags , double magres , const char * damage [ ] , int offmod , int defmod ,
int reload , skill_t sk , int minskill )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
weapon_type * wtype ;
2010-08-08 10:06:34 +02:00
2014-10-14 18:32:04 +02:00
assert ( minskill > 0 ) ;
2014-08-23 09:17:58 +02:00
assert ( resource2weapon ( itype - > rtype ) = = NULL ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
wtype = calloc ( sizeof ( weapon_type ) , 1 ) ;
if ( damage ) {
wtype - > damage [ 0 ] = _strdup ( damage [ 0 ] ) ;
wtype - > damage [ 1 ] = _strdup ( damage [ 1 ] ) ;
}
wtype - > defmod = defmod ;
wtype - > flags | = wflags ;
wtype - > itype = itype ;
wtype - > magres = magres ;
wtype - > minskill = minskill ;
wtype - > offmod = offmod ;
wtype - > reload = reload ;
wtype - > skill = sk ;
itype - > rtype - > wtype = wtype ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
return wtype ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
armor_type * new_armortype ( item_type * itype , double penalty , double magres ,
2014-08-23 09:17:58 +02:00
int prot , unsigned int flags )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
armor_type * atype ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
assert ( itype - > rtype - > atype = = NULL ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
atype = calloc ( sizeof ( armor_type ) , 1 ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
atype - > itype = itype ;
atype - > penalty = penalty ;
atype - > magres = magres ;
atype - > prot = prot ;
atype - > flags = flags ;
itype - > rtype - > atype = atype ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
return atype ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static void pt_register ( potion_type * ptype )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
ptype - > itype - > rtype - > ptype = ptype ;
ptype - > next = potiontypes ;
potiontypes = ptype ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
potion_type * new_potiontype ( item_type * itype , int level )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
potion_type * ptype ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
assert ( resource2potion ( itype - > rtype ) = = NULL ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
ptype = ( potion_type * ) calloc ( sizeof ( potion_type ) , 1 ) ;
ptype - > itype = itype ;
ptype - > level = level ;
pt_register ( ptype ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
return ptype ;
2010-08-08 10:06:34 +02:00
}
2014-06-30 02:02:45 +02:00
void it_set_appearance ( item_type * itype , const char * appearance ) {
2015-07-06 19:53:09 +02:00
assert ( itype & & itype - > rtype & & appearance ) ;
2015-07-06 21:31:27 +02:00
itype - > _appearance [ 0 ] = _strdup ( appearance ) ; //TODO: V595 http://www.viva64.com/en/V595 The 'appearance' pointer was utilized before it was verified against nullptr. Check lines: 336, 337.
2014-06-30 02:35:37 +02:00
itype - > _appearance [ 1 ] = appearance ?
2014-06-30 02:02:45 +02:00
strcat ( strcpy ( ( char * ) malloc ( strlen ( ( char * ) appearance ) + 3 ) , ( char * ) appearance ) , " _p " ) : 0 ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
const resource_type * item2resource ( const item_type * itype )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
return itype ? itype - > rtype : NULL ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
const item_type * resource2item ( const resource_type * rtype )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
return rtype ? rtype - > itype : NULL ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
const weapon_type * resource2weapon ( const resource_type * rtype )
{
2014-08-23 09:17:58 +02:00
return rtype - > wtype ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
const luxury_type * resource2luxury ( const resource_type * rtype )
2010-08-08 10:06:34 +02:00
{
# ifdef AT_LTYPE
2014-08-23 09:17:58 +02:00
attrib * a = a_find ( rtype - > attribs , & at_ltype ) ;
if ( a )
return ( const luxury_type * ) a - > data . v ;
return NULL ;
2010-08-08 10:06:34 +02:00
# else
2014-08-23 09:17:58 +02:00
return rtype - > ltype ;
2010-08-08 10:06:34 +02:00
# endif
}
2011-03-07 08:02:35 +01:00
const potion_type * resource2potion ( const resource_type * rtype )
2010-08-08 10:06:34 +02:00
{
# ifdef AT_PTYPE
2014-08-23 09:17:58 +02:00
attrib * a = a_find ( rtype - > attribs , & at_ptype ) ;
if ( a )
return ( const potion_type * ) a - > data . v ;
return NULL ;
2010-08-08 10:06:34 +02:00
# else
2014-08-23 09:17:58 +02:00
return rtype - > ptype ;
2010-08-08 10:06:34 +02:00
# endif
}
2011-03-07 08:02:35 +01:00
resource_type * rt_find ( const char * name )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
const void * matches ;
resource_type * result = 0 ;
2011-03-07 08:02:35 +01:00
2014-08-23 09:17:58 +02:00
if ( cb_find_prefix ( & cb_resources , name , strlen ( name ) + 1 , & matches , 1 , 0 ) ) {
cb_get_kv ( matches , & result , sizeof ( result ) ) ;
}
return result ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
item * * i_find ( item * * i , const item_type * it )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
while ( * i & & ( * i ) - > type ! = it )
i = & ( * i ) - > next ;
return i ;
2010-08-08 10:06:34 +02:00
}
2014-06-23 16:28:10 +02:00
item * const * i_findc ( item * const * iter , const item_type * it )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
while ( * iter & & ( * iter ) - > type ! = it ) {
iter = & ( * iter ) - > next ;
}
return iter ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
int i_get ( const item * i , const item_type * it )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
i = * i_find ( ( item * * ) & i , it ) ;
if ( i )
return i - > number ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
item * i_add ( item * * pi , item * i )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( i & & i - > type & & ! i - > next ) ;
while ( * pi ) {
2014-08-24 22:30:35 +02:00
int d = strcmp ( ( * pi ) - > type - > rtype - > _name , i - > type - > rtype - > _name ) ;
2014-08-23 09:17:58 +02:00
if ( d > = 0 )
break ;
pi = & ( * pi ) - > next ;
}
if ( * pi & & ( * pi ) - > type = = i - > type ) {
( * pi ) - > number + = i - > number ;
assert ( ( * pi ) - > number > = 0 ) ;
i_free ( i ) ;
}
else {
i - > next = * pi ;
* pi = i ;
}
return * pi ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
void i_merge ( item * * pi , item * * si )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
item * i = * si ;
while ( i ) {
item * itmp ;
while ( * pi ) {
2014-08-24 22:30:35 +02:00
int d = strcmp ( ( * pi ) - > type - > rtype - > _name , i - > type - > rtype - > _name ) ;
2014-08-23 09:17:58 +02:00
if ( d > = 0 )
break ;
pi = & ( * pi ) - > next ;
}
if ( * pi & & ( * pi ) - > type = = i - > type ) {
( * pi ) - > number + = i - > number ;
assert ( ( * pi ) - > number > = 0 ) ;
i_free ( i_remove ( & i , i ) ) ;
}
else {
itmp = i - > next ;
i - > next = * pi ;
* pi = i ;
i = itmp ;
}
2010-08-08 10:06:34 +02:00
}
2014-08-23 09:17:58 +02:00
* si = NULL ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
item * i_change ( item * * pi , const item_type * itype , int delta )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( itype ) ;
while ( * pi ) {
2014-08-24 22:30:35 +02:00
int d = strcmp ( ( * pi ) - > type - > rtype - > _name , itype - > rtype - > _name ) ;
2014-08-23 09:17:58 +02:00
if ( d > = 0 )
break ;
pi = & ( * pi ) - > next ;
2010-08-08 10:06:34 +02:00
}
2014-08-23 09:17:58 +02:00
if ( ! * pi | | ( * pi ) - > type ! = itype ) {
item * i ;
if ( delta = = 0 )
return NULL ;
i = i_new ( itype , delta ) ;
i - > next = * pi ;
* pi = i ;
2010-08-08 10:06:34 +02:00
}
2014-08-23 09:17:58 +02:00
else {
item * i = * pi ;
i - > number + = delta ;
if ( i - > number < 0 ) {
log_error ( " serious accounting error. number of items is %d. \n " , i - > number ) ;
i - > number = 0 ;
}
if ( i - > number = = 0 ) {
* pi = i - > next ;
i_free ( i ) ;
return NULL ;
}
}
return * pi ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
item * i_remove ( item * * pi , item * i )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
assert ( i ) ;
while ( ( * pi ) - > type ! = i - > type )
pi = & ( * pi ) - > next ;
assert ( * pi ) ;
* pi = i - > next ;
i - > next = NULL ;
return i ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static item * icache ;
2010-08-08 10:06:34 +02:00
static int icache_size ;
# define ICACHE_MAX 100
2011-03-07 08:02:35 +01:00
void i_free ( item * i )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
if ( icache_size > = ICACHE_MAX ) {
free ( i ) ;
}
else {
i - > next = icache ;
icache = i ;
+ + icache_size ;
}
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
void i_freeall ( item * * i )
{
2014-08-23 09:17:58 +02:00
item * in ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
while ( * i ) {
in = ( * i ) - > next ;
i_free ( * i ) ;
* i = in ;
}
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
item * i_new ( const item_type * itype , int size )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
item * i ;
if ( icache_size > 0 ) {
i = icache ;
icache = i - > next ;
- - icache_size ;
}
else {
i = malloc ( sizeof ( item ) ) ;
}
assert ( itype ) ;
i - > next = NULL ;
i - > type = itype ;
i - > number = size ;
assert ( i - > number > = 0 ) ;
return i ;
2010-08-08 10:06:34 +02:00
}
# include "region.h"
static int
2011-03-07 08:02:35 +01:00
give_horses ( unit * s , unit * d , const item_type * itype , int n ,
2014-08-23 09:17:58 +02:00
struct order * ord )
{
if ( d = = NULL ) {
int use = use_pooled ( s , item2resource ( itype ) , GET_SLACK , n ) ;
if ( use < n )
use + =
use_pooled ( s , item2resource ( itype ) , GET_RESERVE | GET_POOLED_SLACK ,
n - use ) ;
rsethorses ( s - > region , rhorses ( s - > region ) + use ) ;
return 0 ;
}
return - 1 ; /* use the mechanism */
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
give_money ( unit * s , unit * d , const item_type * itype , int n ,
2014-08-23 09:17:58 +02:00
struct order * ord )
{
if ( d = = NULL ) {
int use = use_pooled ( s , item2resource ( itype ) , GET_SLACK , n ) ;
if ( use < n )
use + =
use_pooled ( s , item2resource ( itype ) , GET_RESERVE | GET_POOLED_SLACK ,
n - use ) ;
rsetmoney ( s - > region , rmoney ( s - > region ) + use ) ;
return 0 ;
}
return - 1 ; /* use the mechanism */
2010-08-08 10:06:34 +02:00
}
# define R_MINOTHER R_SILVER
# define R_MINHERB R_PLAIN_1
# define R_MINPOTION R_FAST
# define R_MINITEM R_IRON
# define MAXITEMS MAX_ITEMS
# define MAXRESOURCES MAX_RESOURCES
# define MAXHERBS MAX_HERBS
# define MAXPOTIONS MAX_POTIONS
# define MAXHERBSPERPOTION 6
2011-03-07 08:02:35 +01:00
const potion_type * oldpotiontype [ MAXPOTIONS + 1 ] ;
2010-08-08 10:06:34 +02:00
/*** alte items ***/
2014-06-30 00:41:04 +02:00
static const char * resourcenames [ MAX_RESOURCES ] = {
2014-08-23 09:17:58 +02:00
" iron " , " stone " , " horse " , " ao_healing " ,
" aots " , " roi " , " rop " , " ao_chastity " ,
" laen " , " fairyboot " , " aoc " , " pegasus " ,
" elvenhorse " , " charger " , " dolphin " , " roqf " , " trollbelt " ,
" aurafocus " , " sphereofinv " , " magicbag " ,
" magicherbbag " , " dreameye " , " p2 " , " seed " , " mallornseed " ,
" money " , " aura " , " permaura " ,
2014-12-12 11:28:37 +01:00
" hp " , " peasant " , " person "
2014-06-22 16:55:14 +02:00
} ;
const resource_type * get_resourcetype ( resource_t type ) {
2014-06-24 16:42:45 +02:00
static int update ;
2014-06-30 00:41:04 +02:00
static struct resource_type * rtypes [ MAX_RESOURCES ] ;
2014-08-23 09:17:58 +02:00
if ( update ! = num_resources ) {
2014-06-24 16:42:45 +02:00
memset ( rtypes , 0 , sizeof ( rtypes ) ) ;
update = num_resources ;
}
const resource_type * rtype = rtypes [ type ] ;
if ( ! rtype ) {
2014-06-30 00:41:04 +02:00
rtype = rtypes [ type ] = rt_find ( resourcenames [ type ] ) ;
2014-06-24 16:42:45 +02:00
}
2014-06-22 16:55:14 +02:00
return rtype ;
}
2014-06-23 16:28:10 +02:00
int get_item ( const unit * u , const item_type * itype )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
const item * i = * i_findc ( & u - > items , itype ) ;
assert ( ! i | | i - > number > = 0 ) ;
return i ? i - > number : 0 ;
2010-08-08 10:06:34 +02:00
}
2014-06-23 16:28:10 +02:00
int set_item ( unit * u , const item_type * itype , int value )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
item * i ;
2011-03-16 05:04:38 +01:00
2014-08-23 09:17:58 +02:00
assert ( itype ) ;
i = * i_find ( & u - > items , itype ) ;
if ( ! i ) {
i = i_add ( & u - > items , i_new ( itype , value ) ) ;
}
else {
i - > number = value ;
assert ( i - > number > = 0 ) ;
}
return value ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_birthdayamulet ( unit * u , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
direction_t d ;
message * msg = msg_message ( " meow " , " " ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
unused_arg ( ord ) ;
unused_arg ( amount ) ;
unused_arg ( itype ) ;
add_message ( & u - > region - > msgs , msg ) ;
for ( d = 0 ; d < MAXDIRECTIONS ; d + + ) {
region * tr = rconnect ( u - > region , d ) ;
if ( tr )
add_message ( & tr - > msgs , msg ) ;
}
msg_release ( msg ) ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
/* t_item::flags */
# define FL_ITEM_CURSED (1<<0)
# define FL_ITEM_NOTLOST (1<<1)
2011-03-07 08:02:35 +01:00
# define FL_ITEM_NOTINBAG (1<<2) /* nicht im Bag Of Holding */
2010-08-08 10:06:34 +02:00
# define FL_ITEM_ANIMAL (1<<3) /* ist ein Tier */
# define FL_ITEM_MOUNT ((1<<4) | FL_ITEM_ANIMAL) /* ist ein Reittier */
/* ------------------------------------------------------------- */
2014-07-15 15:34:42 +02:00
/* Kann auch von Nichtmagier benutzt werden, modifiziert Taktik fuer diese
2010-08-08 10:06:34 +02:00
* Runde um - 1 - 4 Punkte . */
static int
2011-03-07 08:02:35 +01:00
use_tacticcrystal ( unit * u , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
{
int i ;
for ( i = 0 ; i ! = amount ; + + i ) {
int duration = 1 ; /* wirkt nur eine Runde */
curse * c ;
float effect ;
float power = 5 ; /* Widerstand gegen Antimagiesprueche, ist in diesem
Fall egal , da der curse fuer den Kampf gelten soll ,
der vor den Antimagiezaubern passiert */
effect = ( float ) ( rng_int ( ) % 6 - 1 ) ;
c = create_curse ( u , & u - > attribs , ct_find ( " skillmod " ) , power ,
duration , effect , u - > number ) ;
c - > data . i = SK_TACTICS ;
unused_arg ( ord ) ;
}
use_pooled ( u , itype - > rtype , GET_DEFAULT , amount ) ;
ADDMSG ( & u - > faction - > msgs , msg_message ( " use_tacticcrystal " ,
" unit region " , u , u - > region ) ) ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
typedef struct t_item {
2014-08-23 09:17:58 +02:00
const char * name ;
/* [0]: Einzahl fuer eigene; [1]: Mehrzahl fuer eigene;
* [ 2 ] : Einzahl fuer Fremde ; [ 3 ] : Mehrzahl fuer Fremde */
bool is_resource ;
skill_t skill ;
int minskill ;
int gewicht ;
int preis ;
unsigned int flags ;
void ( * benutze_funktion ) ( struct region * , struct unit * , int amount ,
2011-03-07 08:02:35 +01:00
struct order * ) ;
2010-08-08 10:06:34 +02:00
} t_item ;
# include "move.h"
static int
mod_elves_only ( const unit * u , const region * r , skill_t sk , int value )
{
2014-06-30 03:10:02 +02:00
if ( u_race ( u ) = = get_race ( RC_ELF ) )
2014-08-23 09:17:58 +02:00
return value ;
unused_arg ( r ) ;
return - 118 ;
2010-08-08 10:06:34 +02:00
}
static int
mod_dwarves_only ( const unit * u , const region * r , skill_t sk , int value )
{
2014-06-30 05:05:44 +02:00
unused_arg ( r ) ;
2014-07-15 15:34:42 +02:00
if ( u_race ( u ) = = get_race ( RC_DWARF ) | | ( u_race ( u ) - > flags & RCF_IRONGOLEM ) ) {
2014-06-30 03:10:02 +02:00
return value ;
2014-06-30 05:05:44 +02:00
}
return - 118 ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static int heal ( unit * user , int effect )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
int req = unit_max_hp ( user ) * user - > number - user - > hp ;
if ( req > 0 ) {
req = _min ( req , effect ) ;
effect - = req ;
user - > hp + = req ;
}
return effect ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
void
2014-08-23 09:17:58 +02:00
register_item_give ( int ( * foo ) ( struct unit * , struct unit * ,
const struct item_type * , int , struct order * ) , const char * name )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
register_function ( ( pf_generic ) foo , name ) ;
2010-08-08 10:06:34 +02:00
}
void
2014-08-23 09:17:58 +02:00
register_item_use ( int ( * foo ) ( struct unit * , const struct item_type * , int ,
struct order * ) , const char * name )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
register_function ( ( pf_generic ) foo , name ) ;
2010-08-08 10:06:34 +02:00
}
void
2014-08-23 09:17:58 +02:00
register_item_useonother ( int ( * foo ) ( struct unit * , int ,
const struct item_type * , int , struct order * ) , const char * name )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
register_function ( ( pf_generic ) foo , name ) ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_healingpotion ( struct unit * user , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
{
int effect = amount * 400 ;
unit * u = user - > region - > units ;
effect = heal ( user , effect ) ;
while ( effect > 0 & & u ! = NULL ) {
if ( u - > faction = = user - > faction ) {
effect = heal ( u , effect ) ;
}
u = u - > next ;
2010-08-08 10:06:34 +02:00
}
2014-08-23 09:17:58 +02:00
use_pooled ( user , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
amount ) ;
usetpotionuse ( user , itype - > rtype - > ptype ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
ADDMSG ( & user - > faction - > msgs , msg_message ( " usepotion " ,
" unit potion " , user , itype - > rtype ) ) ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_warmthpotion ( struct unit * u , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-06-30 03:10:02 +02:00
if ( u - > faction - > race = = get_race ( RC_INSECT ) ) {
2014-08-23 09:17:58 +02:00
fset ( u , UFL_WARMTH ) ;
}
else {
/* nur fuer insekten: */
cmistake ( u , ord , 163 , MSG_EVENT ) ;
return ECUSTOM ;
}
use_pooled ( u , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
amount ) ;
usetpotionuse ( u , itype - > rtype - > ptype ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
ADDMSG ( & u - > faction - > msgs , msg_message ( " usepotion " ,
" unit potion " , u , itype - > rtype ) ) ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_foolpotion ( struct unit * u , int targetno , const struct item_type * itype ,
2014-08-23 09:17:58 +02:00
int amount , struct order * ord )
{
unit * target = findunit ( targetno ) ;
if ( target = = NULL | | u - > region ! = target - > region ) {
ADDMSG ( & u - > faction - > msgs , msg_feedback ( u , ord , " feedback_unit_not_found " ,
" " ) ) ;
return ECUSTOM ;
}
if ( effskill ( u , SK_STEALTH ) < = effskill ( target , SK_PERCEPTION ) ) {
cmistake ( u , ord , 64 , MSG_EVENT ) ;
return ECUSTOM ;
}
ADDMSG ( & u - > faction - > msgs , msg_message ( " givedumb " ,
" unit recipient amount " , u , target , amount ) ) ;
change_effect ( target , itype - > rtype - > ptype , amount ) ;
use_pooled ( u , itype - > rtype , GET_DEFAULT , amount ) ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_bloodpotion ( struct unit * u , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-08-28 20:01:37 +02:00
if ( u - > number = = 0 | | u_race ( u ) = = get_race ( RC_DAEMON ) ) {
2014-08-23 09:17:58 +02:00
change_effect ( u , itype - > rtype - > ptype , 100 * amount ) ;
}
else {
const race * irace = u_irace ( u ) ;
if ( irace = = u_race ( u ) ) {
static const race * rcfailure ;
if ( ! rcfailure ) {
rcfailure = rc_find ( " smurf " ) ;
if ( ! rcfailure )
rcfailure = rc_find ( " toad " ) ;
}
if ( rcfailure ) {
trigger * trestore = trigger_changerace ( u , u_race ( u ) , irace ) ;
if ( trestore ) {
int duration = 2 + rng_int ( ) % 8 ;
add_trigger ( & u - > attribs , " timer " , trigger_timeout ( duration ,
trestore ) ) ;
u - > irace = NULL ;
u_setrace ( u , rcfailure ) ;
}
}
2010-08-08 10:06:34 +02:00
}
}
2014-08-23 09:17:58 +02:00
use_pooled ( u , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
amount ) ;
usetpotionuse ( u , itype - > rtype - > ptype ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
ADDMSG ( & u - > faction - > msgs , msg_message ( " usepotion " ,
" unit potion " , u , itype - > rtype ) ) ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
# include <attributes/fleechance.h>
static int
2011-03-07 08:02:35 +01:00
use_mistletoe ( struct unit * user , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
int mtoes =
get_pooled ( user , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
user - > number ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
if ( user - > number > mtoes ) {
ADDMSG ( & user - > faction - > msgs , msg_message ( " use_singleperson " ,
" unit item region command " , user , itype - > rtype , user - > region , ord ) ) ;
return - 1 ;
}
use_pooled ( user , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
user - > number ) ;
a_add ( & user - > attribs , make_fleechance ( ( float ) 1.0 ) ) ;
ADDMSG ( & user - > faction - > msgs ,
msg_message ( " use_item " , " unit item " , user , itype - > rtype ) ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
return 0 ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_magicboost ( struct unit * user , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
{
int mtoes =
get_pooled ( user , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
user - > number ) ;
faction * f = user - > faction ;
if ( user - > number > mtoes ) {
ADDMSG ( & user - > faction - > msgs , msg_message ( " use_singleperson " ,
" unit item region command " , user , itype - > rtype , user - > region , ord ) ) ;
return - 1 ;
}
if ( ! is_mage ( user ) | | find_key ( f - > attribs , atoi36 ( " mbst " ) ) ! = NULL ) {
cmistake ( user , user - > thisorder , 214 , MSG_EVENT ) ;
return - 1 ;
}
use_pooled ( user , itype - > rtype , GET_SLACK | GET_RESERVE | GET_POOLED_SLACK ,
user - > number ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
a_add ( & f - > attribs , make_key ( atoi36 ( " mbst " ) ) ) ;
set_level ( user , findskill ( " magic " ) , 3 ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
ADDMSG ( & user - > faction - > msgs , msg_message ( " use_item " ,
" unit item " , user , itype - > rtype ) ) ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
return 0 ;
2010-08-08 10:06:34 +02:00
}
static int
2011-03-07 08:02:35 +01:00
use_snowball ( struct unit * user , const struct item_type * itype , int amount ,
2014-08-23 09:17:58 +02:00
struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
return 0 ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static void init_oldpotions ( void )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
const char * potionnames [ MAX_POTIONS ] = {
" p0 " , " goliathwater " , " p2 " , " p3 " , " ointment " , " peasantblood " , " p6 " ,
" p7 " , " nestwarmth " , " p9 " , " p10 " , " p11 " , " truthpotion " , " p13 " , " p14 "
} ;
int p ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
for ( p = 0 ; p ! = MAXPOTIONS ; + + p ) {
item_type * itype = it_find ( potionnames [ p ] ) ;
if ( itype ! = NULL ) {
oldpotiontype [ p ] = itype - > rtype - > ptype ;
}
2010-08-08 10:06:34 +02:00
}
}
2011-03-07 08:02:35 +01:00
void init_resources ( void )
2010-08-08 10:06:34 +02:00
{
2014-06-22 16:55:14 +02:00
resource_type * rtype ;
2012-05-20 02:23:57 +02:00
2014-12-12 11:28:37 +01:00
rtype = rt_get_or_create ( resourcenames [ R_PERSON ] ) ; // lousy hack
2014-06-30 02:02:45 +02:00
rtype = rt_get_or_create ( resourcenames [ R_PEASANT ] ) ;
2014-06-24 16:42:45 +02:00
rtype - > uchange = res_changepeasants ;
2014-08-23 09:17:58 +02:00
2014-06-24 16:42:45 +02:00
// R_SILVER
2014-06-30 02:02:45 +02:00
rtype = rt_get_or_create ( resourcenames [ R_SILVER ] ) ;
rtype - > flags | = RTF_ITEM | RTF_POOLED ;
2014-06-24 16:42:45 +02:00
rtype - > uchange = res_changeitem ;
2014-06-30 02:02:45 +02:00
rtype - > itype = it_get_or_create ( rtype ) ;
rtype - > itype - > give = give_money ;
2010-08-08 10:06:34 +02:00
2014-06-24 16:42:45 +02:00
// R_PERMAURA
2014-06-30 02:02:45 +02:00
rtype = rt_get_or_create ( resourcenames [ R_PERMAURA ] ) ;
2014-06-24 16:42:45 +02:00
rtype - > uchange = res_changepermaura ;
2014-08-23 09:17:58 +02:00
2014-06-24 16:42:45 +02:00
// R_LIFE
2014-06-30 02:02:45 +02:00
rtype = rt_get_or_create ( resourcenames [ R_LIFE ] ) ;
2014-06-24 16:42:45 +02:00
rtype - > uchange = res_changehp ;
2014-08-23 09:17:58 +02:00
2014-06-24 16:42:45 +02:00
// R_AURA
2014-06-30 02:02:45 +02:00
rtype = rt_get_or_create ( resourcenames [ R_AURA ] ) ;
2014-06-24 16:42:45 +02:00
rtype - > uchange = res_changeaura ;
2010-08-08 10:06:34 +02:00
2014-06-24 16:42:45 +02:00
/* alte typen registrieren: */
init_oldpotions ( ) ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
int get_money ( const unit * u )
2010-08-08 10:06:34 +02:00
{
2014-06-24 16:42:45 +02:00
const struct resource_type * rtype = get_resourcetype ( R_SILVER ) ;
const item * i = u - > items ;
while ( i & & i - > type - > rtype ! = rtype ) {
i = i - > next ;
}
return i ? i - > number : 0 ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
int set_money ( unit * u , int v )
2010-08-08 10:06:34 +02:00
{
2014-06-24 16:42:45 +02:00
const struct resource_type * rtype = get_resourcetype ( R_SILVER ) ;
item * * ip = & u - > items ;
while ( * ip & & ( * ip ) - > type - > rtype ! = rtype ) {
ip = & ( * ip ) - > next ;
}
if ( ( * ip ) = = NULL & & v ) {
i_add ( & u - > items , i_new ( rtype - > itype , v ) ) ;
return v ;
}
if ( ( * ip ) ! = NULL ) {
if ( v ) {
( * ip ) - > number = v ;
assert ( ( * ip ) - > number > = 0 ) ;
2014-08-23 09:17:58 +02:00
}
else {
2014-06-24 16:42:45 +02:00
i_remove ( ip , * ip ) ;
}
}
2010-08-08 10:06:34 +02:00
return v ;
}
2011-03-07 08:02:35 +01:00
int change_money ( unit * u , int v )
2010-08-08 10:06:34 +02:00
{
2014-06-24 16:42:45 +02:00
const struct resource_type * rtype = get_resourcetype ( R_SILVER ) ;
item * * ip = & u - > items ;
while ( * ip & & ( * ip ) - > type - > rtype ! = rtype ) {
ip = & ( * ip ) - > next ;
}
if ( ( * ip ) = = NULL & & v ) {
i_add ( & u - > items , i_new ( rtype - > itype , v ) ) ;
return v ;
}
if ( ( * ip ) ! = NULL ) {
item * i = * ip ;
if ( i - > number + v ! = 0 ) {
i - > number + = v ;
assert ( i - > number > = 0 ) ;
return i - > number ;
2014-08-23 09:17:58 +02:00
}
else {
2014-06-24 16:42:45 +02:00
i_free ( i_remove ( ip , * ip ) ) ;
}
}
return 0 ;
2010-08-08 10:06:34 +02:00
}
2012-05-23 07:01:48 +02:00
static int add_resourcename_cb ( const void * match , const void * key , size_t keylen , void * data )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
struct locale * lang = ( struct locale * ) data ;
int i = locale_index ( lang ) ;
critbit_tree * cb = rnames + i ;
resource_type * rtype ;
2010-08-08 10:06:34 +02:00
2014-08-23 09:17:58 +02:00
cb_get_kv ( match , & rtype , sizeof ( rtype ) ) ;
for ( i = 0 ; i ! = 2 ; + + i ) {
char buffer [ 128 ] ;
2015-01-08 20:55:29 +01:00
const char * name = LOC ( lang , resourcename ( rtype , ( i = = 0 ) ? 0 : NMF_PLURAL ) ) ;
2014-08-23 09:17:58 +02:00
if ( name & & transliterate ( buffer , sizeof ( buffer ) , name ) ) {
size_t len = strlen ( buffer ) ;
assert ( len + sizeof ( rtype ) < sizeof ( buffer ) ) ;
len = cb_new_kv ( buffer , len , & rtype , sizeof ( rtype ) , buffer ) ;
cb_insert ( cb , buffer , len ) ;
}
2012-05-23 07:01:48 +02:00
}
2014-08-23 09:17:58 +02:00
return 0 ;
2012-05-23 07:01:48 +02:00
}
2010-08-08 10:06:34 +02:00
2012-05-23 07:01:48 +02:00
const resource_type * findresourcetype ( const char * name , const struct locale * lang )
{
2014-08-23 09:17:58 +02:00
int i = locale_index ( lang ) ;
critbit_tree * cb = rnames + i ;
char buffer [ 128 ] ;
2012-05-23 07:01:48 +02:00
2014-08-23 09:17:58 +02:00
if ( transliterate ( buffer , sizeof ( buffer ) , name ) ) {
const void * match ;
if ( ! cb - > root ) {
/* first-time initialization of resource names for this locale */
cb_foreach ( & cb_resources , " " , 0 , add_resourcename_cb , ( void * ) lang ) ;
}
if ( cb_find_prefix ( cb , buffer , strlen ( buffer ) , & match , 1 , 0 ) ) {
const resource_type * rtype = 0 ;
cb_get_kv ( match , ( void * ) & rtype , sizeof ( rtype ) ) ;
return rtype ;
}
2012-05-23 07:01:48 +02:00
}
2014-08-23 09:17:58 +02:00
else {
log_debug ( " findresourcetype: transliterate failed for '%s' \n " , name ) ;
2012-05-23 07:01:48 +02:00
}
2014-08-23 09:17:58 +02:00
return 0 ;
2010-08-08 10:06:34 +02:00
}
attrib_type at_showitem = {
2014-08-23 09:17:58 +02:00
" showitem "
2010-08-08 10:06:34 +02:00
} ;
2012-05-21 22:18:05 +02:00
static int add_itemname_cb ( const void * match , const void * key , size_t keylen , void * data )
2010-08-08 10:06:34 +02:00
{
2014-06-30 01:39:53 +02:00
struct locale * lang = ( struct locale * ) data ;
critbit_tree * cb = inames + locale_index ( lang ) ;
resource_type * rtype ;
2010-08-08 10:06:34 +02:00
2014-06-30 01:39:53 +02:00
cb_get_kv ( match , & rtype , sizeof ( rtype ) ) ;
if ( rtype - > itype ) {
int i ;
for ( i = 0 ; i ! = 2 ; + + i ) {
char buffer [ 128 ] ;
2015-01-08 20:55:29 +01:00
const char * name = LOC ( lang , resourcename ( rtype , ( i = = 0 ) ? 0 : NMF_PLURAL ) ) ;
2014-06-30 01:39:53 +02:00
if ( name & & transliterate ( buffer , sizeof ( buffer ) , name ) ) {
size_t len = strlen ( buffer ) ;
assert ( len + sizeof ( rtype - > itype ) < sizeof ( buffer ) ) ;
len = cb_new_kv ( buffer , len , & rtype - > itype , sizeof ( rtype - > itype ) , buffer ) ;
cb_insert ( cb , buffer , len ) ;
}
}
2012-05-21 22:18:05 +02:00
}
2014-06-30 01:39:53 +02:00
return 0 ;
2012-05-21 22:18:05 +02:00
}
2012-05-19 20:26:46 +02:00
2012-05-21 22:18:05 +02:00
const item_type * finditemtype ( const char * name , const struct locale * lang )
{
2014-08-23 09:17:58 +02:00
int i = locale_index ( lang ) ;
critbit_tree * cb = inames + i ;
char buffer [ 128 ] ;
2012-05-21 22:18:05 +02:00
2014-08-23 09:17:58 +02:00
assert ( name ) ;
if ( transliterate ( buffer , sizeof ( buffer ) , name ) ) {
const void * match ;
if ( ! cb - > root ) {
/* first-time initialization of item names for this locale */
cb_foreach ( & cb_resources , " " , 0 , add_itemname_cb , ( void * ) lang ) ;
}
if ( cb_find_prefix ( cb , buffer , strlen ( buffer ) , & match , 1 , 0 ) ) {
const item_type * itype = 0 ;
cb_get_kv ( match , ( void * ) & itype , sizeof ( itype ) ) ;
return itype ;
}
2012-05-21 22:18:05 +02:00
}
2014-08-23 09:17:58 +02:00
else {
log_debug ( " finditemtype: transliterate failed for '%s' \n " , name ) ;
2012-05-21 22:18:05 +02:00
}
2014-08-23 09:17:58 +02:00
return 0 ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static void init_resourcelimit ( attrib * a )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
a - > data . v = calloc ( sizeof ( resource_limit ) , 1 ) ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
static void finalize_resourcelimit ( attrib * a )
2010-08-08 10:06:34 +02:00
{
2014-08-23 09:17:58 +02:00
free ( a - > data . v ) ;
2010-08-08 10:06:34 +02:00
}
attrib_type at_resourcelimit = {
2014-08-23 09:17:58 +02:00
" resourcelimit " ,
init_resourcelimit ,
finalize_resourcelimit ,
2010-08-08 10:06:34 +02:00
} ;
2011-03-07 08:02:35 +01:00
static item * default_spoil ( const struct race * rc , int size )
2011-02-27 09:36:38 +01:00
{
2014-08-23 09:17:58 +02:00
item * itm = NULL ;
2011-02-27 09:36:38 +01:00
2014-08-23 09:17:58 +02:00
if ( rng_int ( ) % 100 < RACESPOILCHANCE ) {
char spoilname [ 32 ] ;
const item_type * itype ;
2011-03-07 08:02:35 +01:00
2014-08-24 21:49:55 +02:00
sprintf ( spoilname , " %sspoil " , rc - > _name ) ;
2014-08-23 09:17:58 +02:00
itype = it_find ( spoilname ) ;
if ( itype ! = NULL ) {
i_add ( & itm , i_new ( itype , size ) ) ;
}
2011-02-27 09:36:38 +01:00
}
2014-08-23 09:17:58 +02:00
return itm ;
2011-02-27 09:36:38 +01:00
}
2014-12-30 23:49:50 +01:00
int free_itype ( item_type * itype ) {
2014-08-23 09:17:58 +02:00
free ( itype - > construction ) ;
free ( itype - > _appearance [ 0 ] ) ;
free ( itype - > _appearance [ 1 ] ) ;
free ( itype ) ;
return 0 ;
2012-05-19 20:26:46 +02:00
}
int free_rtype_cb ( const void * match , const void * key , size_t keylen , void * cbdata ) {
2014-08-23 09:17:58 +02:00
resource_type * rtype ;
cb_get_kv ( match , & rtype , sizeof ( rtype ) ) ;
2014-08-24 22:30:35 +02:00
free ( rtype - > _name ) ;
2014-12-30 23:49:50 +01:00
if ( rtype - > itype ) {
free_itype ( rtype - > itype ) ;
}
2014-08-23 09:17:58 +02:00
free ( rtype ) ;
return 0 ;
2012-05-19 20:26:46 +02:00
}
2014-12-30 23:49:50 +01:00
void free_resources ( void )
2011-03-16 05:04:38 +01:00
{
2014-06-24 16:42:45 +02:00
int i ;
2012-05-20 03:50:28 +02:00
2014-06-24 16:42:45 +02:00
memset ( ( void * ) oldpotiontype , 0 , sizeof ( oldpotiontype ) ) ;
2014-12-31 20:01:01 +01:00
while ( luxurytypes ) {
luxury_type * next = luxurytypes - > next ;
free ( luxurytypes ) ;
luxurytypes = next ;
}
2014-06-24 16:42:45 +02:00
cb_foreach ( & cb_resources , " " , 0 , free_rtype_cb , 0 ) ;
cb_clear ( & cb_resources ) ;
+ + num_resources ;
2014-08-23 09:17:58 +02:00
for ( i = 0 ; i ! = MAXLOCALES ; + + i ) {
2014-06-30 02:02:45 +02:00
cb_clear ( inames + i ) ;
cb_clear ( rnames + i ) ;
2014-06-24 16:42:45 +02:00
}
2011-03-16 05:04:38 +01:00
}
2011-03-07 08:02:35 +01:00
void register_resources ( void )
{
2014-08-23 09:17:58 +02:00
static bool registered = false ;
if ( registered ) return ;
registered = true ;
register_function ( ( pf_generic ) mod_elves_only , " mod_elves_only " ) ;
register_function ( ( pf_generic ) mod_dwarves_only , " mod_dwarves_only " ) ;
register_function ( ( pf_generic ) res_changeitem , " changeitem " ) ;
register_function ( ( pf_generic ) res_changeperson , " changeperson " ) ;
register_function ( ( pf_generic ) res_changepeasants , " changepeasants " ) ;
register_function ( ( pf_generic ) res_changepermaura , " changepermaura " ) ;
register_function ( ( pf_generic ) res_changehp , " changehp " ) ;
register_function ( ( pf_generic ) res_changeaura , " changeaura " ) ;
register_function ( ( pf_generic ) default_spoil , " defaultdrops " ) ;
register_item_use ( use_potion , " usepotion " ) ;
register_item_use ( use_potion_delayed , " usepotion_delayed " ) ;
register_item_use ( use_tacticcrystal , " use_tacticcrystal " ) ;
register_item_use ( use_birthdayamulet , " use_birthdayamulet " ) ;
register_item_use ( use_warmthpotion , " usewarmthpotion " ) ;
register_item_use ( use_bloodpotion , " usebloodpotion " ) ;
register_item_use ( use_healingpotion , " usehealingpotion " ) ;
register_item_useonother ( use_foolpotion , " usefoolpotion " ) ;
register_item_use ( use_mistletoe , " usemistletoe " ) ;
register_item_use ( use_magicboost , " usemagicboost " ) ;
register_item_use ( use_snowball , " usesnowball " ) ;
register_item_give ( give_horses , " givehorses " ) ;
2010-08-08 10:06:34 +02:00
}