2015-07-06 19:53:09 +02:00
/*
2010-08-08 10:06:34 +02:00
+ - - - - - - - - - - - - - - - - - - - + Christian Schlittchen < corwin @ amber . kn - bremen . de >
| | Enno Rehling < enno @ eressea . de >
| Eressea PBEM host | Katja Zedel < katze @ felidae . kn - bremen . de >
2014-08-08 01:03:46 +02:00
| ( c ) 1998 - 2014 | Henning Peters < faroul @ beyond . kn - bremen . de >
2010-08-08 10:06:34 +02:00
| | Ingo Wilken < Ingo . Wilken @ informatik . uni - oldenburg . de >
+ - - - - - - - - - - - - - - - - - - - + Stefan Reich < reich @ halbling . de >
2014-08-08 01:03:46 +02:00
This program may not be used , modified or distributed
2010-08-08 10:06:34 +02:00
without prior permission by the authors of Eressea .
*/
# include <platform.h>
# include <kernel/config.h>
# include "give.h"
# include "economy.h"
2014-11-03 08:40:58 +01:00
# include "laws.h"
2010-08-08 10:06:34 +02:00
/* kernel includes */
2012-06-03 22:39:42 +02:00
# include <kernel/curse.h>
2010-08-08 10:06:34 +02:00
# include <kernel/faction.h>
# include <kernel/item.h>
2014-06-09 18:54:48 +02:00
# include <kernel/messages.h>
2010-08-08 10:06:34 +02:00
# include <kernel/order.h>
2014-11-03 08:40:58 +01:00
# include <kernel/plane.h>
2010-08-08 10:06:34 +02:00
# include <kernel/pool.h>
# include <kernel/race.h>
# include <kernel/region.h>
# include <kernel/ship.h>
# include <kernel/terrain.h>
# include <kernel/unit.h>
/* attributes includes */
# include <attributes/racename.h>
# include <attributes/orcification.h>
/* util includes */
# include <util/attrib.h>
# include <util/base36.h>
# include <util/event.h>
# include <util/log.h>
2014-11-03 08:40:58 +01:00
# include <util/parser.h>
2010-08-08 10:06:34 +02:00
/* libc includes */
# include <assert.h>
# include <limits.h>
# include <stdlib.h>
/* Wieviel Fremde eine Partei pro Woche aufnehmen kangiven */
2011-03-07 08:02:35 +01:00
# define RESERVE_DONATIONS /* shall we reserve objects given to us by other factions? */
# define RESERVE_GIVE /* reserve anything that's given from one unit to another? */
2010-08-08 10:06:34 +02:00
2015-03-13 21:56:18 +01:00
static int max_transfers ( void ) {
2015-03-13 21:10:39 +01:00
return get_param_int ( global . parameters , " rules.give.max_men " , 5 ) ;
}
2011-03-07 08:02:35 +01:00
static int GiveRestriction ( void )
{
2015-05-22 16:23:18 +02:00
return get_param_int ( global . parameters , " GiveRestriction " , 0 ) ;
2010-08-08 10:06:34 +02:00
}
2014-11-03 08:40:58 +01:00
static void feedback_give_not_allowed ( unit * u , order * ord )
{
ADDMSG ( & u - > faction - > msgs , msg_feedback ( u , ord , " feedback_give_forbidden " ,
" " ) ) ;
}
static bool can_give ( const unit * u , const unit * u2 , const item_type * itype , int mask )
{
if ( u2 ) {
if ( u - > faction ! = u2 - > faction ) {
int rule = rule_give ( ) ;
if ( itype ) {
assert ( mask = = 0 ) ;
if ( itype - > rtype - > ltype )
mask | = GIVE_LUXURIES ;
else if ( fval ( itype , ITF_HERB ) )
mask | = GIVE_HERBS ;
else
mask | = GIVE_GOODS ;
}
return ( rule & mask ) ! = 0 ;
}
}
else {
int rule = rule_give ( ) ;
return ( rule & GIVE_PEASANTS ) ! = 0 ;
}
return true ;
}
2010-08-08 10:06:34 +02:00
static void
2011-03-07 08:02:35 +01:00
add_give ( unit * u , unit * u2 , int given , int received ,
2014-08-08 01:03:46 +02:00
const resource_type * rtype , struct order * ord , int error )
2010-08-08 10:06:34 +02:00
{
2014-08-08 01:03:46 +02:00
if ( error ) {
cmistake ( u , ord , error , MSG_COMMERCE ) ;
}
else if ( u2 = = NULL ) {
ADDMSG ( & u - > faction - > msgs ,
msg_message ( " give_peasants " , " unit resource amount " , u , rtype , given ) ) ;
}
else if ( u2 - > faction ! = u - > faction ) {
message * msg ;
msg =
msg_message ( " give " , " unit target resource amount " , u , u2 , rtype , given ) ;
add_message ( & u - > faction - > msgs , msg ) ;
msg_release ( msg ) ;
msg =
msg_message ( " receive " , " unit target resource amount " , u , u2 , rtype ,
received ) ;
add_message ( & u2 - > faction - > msgs , msg ) ;
msg_release ( msg ) ;
}
2010-08-08 10:06:34 +02:00
}
2012-06-24 07:41:07 +02:00
static bool limited_give ( const item_type * type )
2010-08-08 10:06:34 +02:00
{
2014-08-08 01:03:46 +02:00
/* trade only money 2:1, if at all */
return ( type - > rtype = = get_resourcetype ( R_SILVER ) ) ;
2010-08-08 10:06:34 +02:00
}
2011-03-07 08:02:35 +01:00
int give_quota ( const unit * src , const unit * dst , const item_type * type ,
2014-08-08 01:03:46 +02:00
int n )
2010-08-08 10:06:34 +02:00
{
2015-05-15 19:08:44 +02:00
double divisor ;
2010-08-08 10:06:34 +02:00
2014-08-08 01:03:46 +02:00
if ( ! limited_give ( type ) ) {
return n ;
}
if ( dst & & src & & src - > faction ! = dst - > faction ) {
divisor = get_param_flt ( global . parameters , " rules.items.give_divisor " , 1 ) ;
assert ( divisor = = 0 | | divisor > = 1 ) ;
if ( divisor > = 1 ) {
/* predictable > correct: */
int x = ( int ) ( n / divisor ) ;
return x ;
}
}
2010-08-08 10:06:34 +02:00
return n ;
}
int
2011-03-07 08:02:35 +01:00
give_item ( int want , const item_type * itype , unit * src , unit * dest ,
2014-08-08 01:03:46 +02:00
struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-08-08 01:03:46 +02:00
short error = 0 ;
int n , r ;
assert ( itype ! = NULL ) ;
n = get_pooled ( src , item2resource ( itype ) , GET_SLACK | GET_POOLED_SLACK , want ) ;
n = _min ( want , n ) ;
r = n ;
if ( dest & & src - > faction ! = dest - > faction
& & src - > faction - > age < GiveRestriction ( ) ) {
if ( ord ! = NULL ) {
ADDMSG ( & src - > faction - > msgs , msg_feedback ( src , ord , " giverestriction " ,
" turns " , GiveRestriction ( ) ) ) ;
}
return - 1 ;
}
else if ( n = = 0 ) {
2014-12-12 11:28:37 +01:00
int reserve = get_reservation ( src , itype ) ;
2014-08-08 01:03:46 +02:00
if ( reserve ) {
msg_feedback ( src , ord , " nogive_reserved " , " resource reservation " ,
itype - > rtype , reserve ) ;
return - 1 ;
}
error = 36 ;
}
else if ( itype - > flags & ITF_CURSED ) {
error = 25 ;
}
else if ( itype - > give = = NULL | | itype - > give ( src , dest , itype , n , ord ) ! = 0 ) {
int use = use_pooled ( src , item2resource ( itype ) , GET_SLACK , n ) ;
if ( use < n )
use + =
use_pooled ( src , item2resource ( itype ) , GET_POOLED_SLACK ,
n - use ) ;
if ( dest ) {
r = give_quota ( src , dest , itype , n ) ;
i_change ( & dest - > items , itype , r ) ;
2010-08-08 10:06:34 +02:00
# ifdef RESERVE_GIVE
# ifdef RESERVE_DONATIONS
2014-12-12 11:28:37 +01:00
change_reservation ( dest , itype , r ) ;
2010-08-08 10:06:34 +02:00
# else
2014-08-08 01:03:46 +02:00
if ( src - > faction = = dest - > faction ) {
change_reservation ( dest , item2resource ( itype ) , r ) ;
}
2010-08-08 10:06:34 +02:00
# endif
# endif
# if MUSEUM_MODULE && defined(TODO)
2014-08-08 01:03:46 +02:00
/* TODO: use a trigger for the museum warden! */
if ( a_find ( dest - > attribs , & at_warden ) ) {
warden_add_give ( src , dest , itype , r ) ;
}
2010-08-08 10:06:34 +02:00
# endif
2014-08-08 01:03:46 +02:00
handle_event ( dest - > attribs , " receive " , src ) ;
}
handle_event ( src - > attribs , " give " , dest ) ;
}
add_give ( src , dest , n , r , item2resource ( itype ) , ord , error ) ;
if ( error )
return - 1 ;
return 0 ;
2010-08-08 10:06:34 +02:00
}
2014-12-10 23:04:54 +01:00
static bool can_give_men ( const unit * u , order * ord , message * * msg ) {
if ( u_race ( u ) = = get_race ( RC_SNOTLING ) ) {
/* snotlings may not be given to the peasants. */
if ( msg ) * msg = msg_error ( u , ord , 307 ) ;
}
else if ( unit_has_cursed_item ( u ) ) {
if ( msg ) * msg = msg_error ( u , ord , 78 ) ;
}
else if ( has_skill ( u , SK_MAGIC ) ) {
/* cannot give units to and from magicians */
if ( msg ) * msg = msg_error ( u , ord , 158 ) ;
}
else if ( fval ( u , UFL_HUNGER ) ) {
/* hungry people cannot be given away */
if ( msg ) * msg = msg_error ( u , ord , 73 ) ;
}
else if ( fval ( u , UFL_LOCKED ) | | is_cursed ( u - > attribs , C_SLAVE , 0 ) ) {
if ( msg ) * msg = msg_error ( u , ord , 74 ) ;
}
else {
return true ;
}
return false ;
}
2014-12-10 21:17:00 +01:00
message * give_men ( int n , unit * u , unit * u2 , struct order * ord )
2010-08-08 10:06:34 +02:00
{
2014-08-08 01:03:46 +02:00
ship * sh ;
int k = 0 ;
int error = 0 ;
2014-12-10 23:04:54 +01:00
message * msg ;
2015-04-28 17:40:41 +02:00
int maxt = max_transfers ( ) ;
2014-12-10 23:04:54 +01:00
assert ( u2 ) ;
if ( ! can_give_men ( u , ord , & msg ) ) {
return msg ;
}
2014-08-08 01:03:46 +02:00
2014-12-10 23:04:54 +01:00
if ( u - > faction ! = u2 - > faction & & u - > faction - > age < GiveRestriction ( ) ) {
2014-12-10 21:17:00 +01:00
return msg_feedback ( u , ord , " giverestriction " ,
" turns " , GiveRestriction ( ) ) ;
2014-08-08 01:03:46 +02:00
}
else if ( u = = u2 ) {
error = 10 ;
}
2014-12-10 23:04:54 +01:00
else if ( u2 - > number & & ( fval ( u , UFL_HERO ) ! = fval ( u2 , UFL_HERO ) ) ) {
2014-08-08 01:03:46 +02:00
/* heroes may not be given to non-heroes and vice versa */
error = 75 ;
}
2014-12-10 23:04:54 +01:00
else if ( unit_has_cursed_item ( u2 ) ) {
2014-08-08 01:03:46 +02:00
error = 78 ;
}
2014-12-10 23:04:54 +01:00
else if ( fval ( u2 , UFL_LOCKED ) | | is_cursed ( u2 - > attribs , C_SLAVE , 0 ) ) {
2014-08-08 01:03:46 +02:00
error = 75 ;
}
2014-12-10 23:04:54 +01:00
else if ( ! ucontact ( u2 , u ) ) {
2014-12-10 21:17:00 +01:00
return msg_feedback ( u , ord , " feedback_no_contact " ,
" target " , u2 ) ;
2014-08-08 01:03:46 +02:00
}
2014-12-10 23:04:54 +01:00
else if ( has_skill ( u2 , SK_MAGIC ) ) {
2014-08-08 01:03:46 +02:00
/* cannot give units to and from magicians */
error = 158 ;
}
2014-12-10 23:04:54 +01:00
else if ( fval ( u , UFL_WERE ) ! = fval ( u2 , UFL_WERE ) ) {
2014-08-08 01:03:46 +02:00
/* werewolves can't be given to non-werewolves and vice-versa */
error = 312 ;
}
2014-12-10 23:04:54 +01:00
else if ( u2 - > number ! = 0 & & u_race ( u2 ) ! = u_race ( u ) ) {
2014-08-24 21:49:55 +02:00
log_debug ( " faction %s attempts to give %s to %s. \n " , itoa36 ( u - > faction - > no ) , u_race ( u ) - > _name , u_race ( u2 ) - > _name ) ;
2014-08-08 01:03:46 +02:00
error = 139 ;
}
2014-12-10 23:04:54 +01:00
else if ( get_racename ( u2 - > attribs ) | | get_racename ( u - > attribs ) ) {
2014-08-08 01:03:46 +02:00
error = 139 ;
}
2014-12-10 23:04:54 +01:00
else if ( u2 - > faction ! = u - > faction & & ! rule_transfermen ( ) ) {
2014-08-08 01:03:46 +02:00
error = 74 ;
}
else {
if ( n > u - > number )
n = u - > number ;
if ( u2 & & n + u2 - > number > UNIT_MAXSIZE ) {
n = UNIT_MAXSIZE - u2 - > number ;
ADDMSG ( & u - > faction - > msgs , msg_feedback ( u , ord , " error_unit_size " ,
" maxsize " , UNIT_MAXSIZE ) ) ;
assert ( n > = 0 ) ;
2010-08-08 10:06:34 +02:00
}
2014-08-08 01:03:46 +02:00
if ( n = = 0 ) {
error = 96 ;
}
2014-12-10 23:04:54 +01:00
else if ( u - > faction ! = u2 - > faction ) {
2015-07-06 19:53:09 +02:00
if ( maxt > = 0 & & u2 - > faction - > newbies + n > maxt ) {
2014-08-08 01:03:46 +02:00
error = 129 ;
}
else if ( u_race ( u ) ! = u2 - > faction - > race ) {
if ( u2 - > faction - > race ! = get_race ( RC_HUMAN ) ) {
error = 120 ;
}
else if ( count_migrants ( u2 - > faction ) + n >
count_maxmigrants ( u2 - > faction ) ) {
error = 128 ;
}
else if ( has_limited_skills ( u ) | | has_limited_skills ( u2 ) ) {
error = 154 ;
}
else if ( u2 - > number ! = 0 ) {
error = 139 ;
}
}
}
}
2014-12-10 23:04:54 +01:00
if ( has_skill ( u , SK_ALCHEMY ) | | has_skill ( u2 , SK_ALCHEMY ) ) {
2014-08-08 01:03:46 +02:00
k = count_skill ( u2 - > faction , SK_ALCHEMY ) ;
/* Falls die Zieleinheit keine Alchemisten sind, werden sie nun
* welche . */
if ( ! has_skill ( u2 , SK_ALCHEMY ) & & has_skill ( u , SK_ALCHEMY ) )
k + = u2 - > number ;
/* Wenn in eine Alchemisteneinheit Personen verschoben werden */
if ( has_skill ( u2 , SK_ALCHEMY ) & & ! has_skill ( u , SK_ALCHEMY ) )
k + = n ;
2015-07-06 19:53:09 +02:00
/* Wenn Parteigrenzen überschritten werden */
2014-08-08 01:03:46 +02:00
if ( u2 - > faction ! = u - > faction )
k + = n ;
/* wird das Alchemistenmaximum ueberschritten ? */
if ( k > skill_limit ( u2 - > faction , SK_ALCHEMY ) ) {
error = 156 ;
}
}
if ( error = = 0 ) {
2014-12-10 23:04:54 +01:00
if ( u2 - > number = = 0 ) {
2014-08-08 01:03:46 +02:00
set_racename ( & u2 - > attribs , get_racename ( u - > attribs ) ) ;
u_setrace ( u2 , u_race ( u ) ) ;
u2 - > irace = u - > irace ;
if ( fval ( u , UFL_HERO ) )
fset ( u2 , UFL_HERO ) ;
else
freset ( u2 , UFL_HERO ) ;
2010-08-08 10:06:34 +02:00
}
2014-08-08 01:03:46 +02:00
2015-07-06 19:53:09 +02:00
/* Einheiten von Schiffen können nicht NACH in von
* Nicht - alliierten bewachten Regionen ausführen */
2014-12-10 23:04:54 +01:00
sh = leftship ( u ) ;
if ( sh ) {
set_leftship ( u2 , sh ) ;
2014-08-08 01:03:46 +02:00
}
2014-12-10 23:04:54 +01:00
transfermen ( u , u2 , n ) ;
2015-07-06 19:53:09 +02:00
if ( maxt > = 0 & & u - > faction ! = u2 - > faction ) {
2014-12-10 23:04:54 +01:00
u2 - > faction - > newbies + = n ;
2014-08-08 01:03:46 +02:00
}
}
if ( error > 0 ) {
2014-12-10 21:17:00 +01:00
return msg_error ( u , ord , error ) ;
2014-08-08 01:03:46 +02:00
}
else if ( u2 - > faction ! = u - > faction ) {
message * msg = msg_message ( " give_person " , " unit target amount " , u , u2 , n ) ;
add_message ( & u2 - > faction - > msgs , msg ) ;
2014-12-10 21:17:00 +01:00
return msg ;
2014-08-08 01:03:46 +02:00
}
2014-12-10 21:17:00 +01:00
return NULL ;
2010-08-08 10:06:34 +02:00
}
2014-12-10 22:14:25 +01:00
message * disband_men ( int n , unit * u , struct order * ord ) {
2014-12-10 23:04:54 +01:00
message * msg ;
if ( ! can_give_men ( u , ord , & msg ) ) {
return msg ;
}
transfermen ( u , NULL , n ) ;
# ifdef ORCIFICATION
if ( u_race ( u ) = = get_race ( RC_SNOTLING ) & & ! fval ( u - > region , RF_ORCIFIED ) ) {
attrib * a = a_find ( u - > region - > attribs , & at_orcification ) ;
if ( ! a ) {
a = a_add ( & u - > region - > attribs , a_new ( & at_orcification ) ) ;
}
a - > data . i + = n ;
}
# endif
2014-12-11 08:35:05 +01:00
if ( fval ( u - > region - > terrain , SEA_REGION ) ) {
return msg_message ( " give_person_ocean " , " unit amount " , u , n ) ;
}
2014-12-10 23:04:54 +01:00
return msg_message ( " give_person_peasants " , " unit amount " , u , n ) ;
2014-12-10 22:14:25 +01:00
}
2011-03-07 08:02:35 +01:00
void give_unit ( unit * u , unit * u2 , order * ord )
2010-08-08 10:06:34 +02:00
{
2015-07-06 21:31:27 +02:00
region * r = u - > region ; //TODO: V595 http://www.viva64.com/en/V595 The 'u' pointer was utilized before it was verified against nullptr. Check lines: 403, 406.
2015-06-08 09:06:20 +02:00
int maxt = max_transfers ( ) ;
2014-08-08 01:03:46 +02:00
2015-07-06 19:53:09 +02:00
assert ( u ) ;
2014-08-08 01:03:46 +02:00
if ( ! rule_transfermen ( ) & & u - > faction ! = u2 - > faction ) {
cmistake ( u , ord , 74 , MSG_COMMERCE ) ;
return ;
}
if ( u & & unit_has_cursed_item ( u ) ) {
cmistake ( u , ord , 78 , MSG_COMMERCE ) ;
return ;
}
if ( fval ( u , UFL_HERO ) ) {
cmistake ( u , ord , 75 , MSG_COMMERCE ) ;
return ;
}
if ( fval ( u , UFL_LOCKED ) | | fval ( u , UFL_HUNGER ) ) {
cmistake ( u , ord , 74 , MSG_COMMERCE ) ;
return ;
}
if ( u2 = = NULL ) {
2014-12-11 08:35:05 +01:00
message * msg ;
2014-08-08 01:03:46 +02:00
if ( fval ( r - > terrain , SEA_REGION ) ) {
2014-12-11 08:35:05 +01:00
msg = disband_men ( u - > number , u , ord ) ;
if ( msg ) {
ADDMSG ( & u - > faction - > msgs , msg ) ;
}
else {
cmistake ( u , ord , 152 , MSG_COMMERCE ) ;
}
2014-08-08 01:03:46 +02:00
}
2014-12-12 20:53:39 +01:00
else {
2014-08-08 01:03:46 +02:00
unit * u3 ;
for ( u3 = r - > units ; u3 ; u3 = u3 - > next )
if ( u3 - > faction = = u - > faction & & u ! = u3 )
break ;
if ( u3 ) {
while ( u - > items ) {
item * iold = i_remove ( & u - > items , u - > items ) ;
item * inew = * i_find ( & u3 - > items , iold - > type ) ;
if ( inew = = NULL )
i_add ( & u3 - > items , iold ) ;
else {
inew - > number + = iold - > number ;
i_free ( iold ) ;
}
}
}
2014-12-10 22:14:25 +01:00
msg = disband_men ( u - > number , u , ord ) ;
2014-12-10 21:17:00 +01:00
if ( msg ) {
ADDMSG ( & u - > faction - > msgs , msg ) ;
}
else {
cmistake ( u , ord , 153 , MSG_COMMERCE ) ;
}
2014-08-08 01:03:46 +02:00
}
return ;
}
if ( ! alliedunit ( u2 , u - > faction , HELP_GIVE ) & & ucontact ( u2 , u ) = = 0 ) {
ADDMSG ( & u - > faction - > msgs , msg_feedback ( u , ord , " feedback_no_contact " ,
" target " , u2 ) ) ;
return ;
}
if ( u - > number = = 0 ) {
cmistake ( u , ord , 105 , MSG_COMMERCE ) ;
return ;
}
2015-06-08 09:06:20 +02:00
if ( maxt > = 0 & & u - > faction ! = u2 - > faction ) {
if ( u2 - > faction - > newbies + u - > number > maxt ) {
cmistake ( u , ord , 129 , MSG_COMMERCE ) ;
return ;
}
2014-08-08 01:03:46 +02:00
}
if ( u_race ( u ) ! = u2 - > faction - > race ) {
if ( u2 - > faction - > race ! = get_race ( RC_HUMAN ) ) {
cmistake ( u , ord , 120 , MSG_COMMERCE ) ;
return ;
}
if ( count_migrants ( u2 - > faction ) + u - > number >
count_maxmigrants ( u2 - > faction ) ) {
cmistake ( u , ord , 128 , MSG_COMMERCE ) ;
return ;
2010-08-08 10:06:34 +02:00
}
2014-08-08 01:03:46 +02:00
if ( has_limited_skills ( u ) ) {
cmistake ( u , ord , 154 , MSG_COMMERCE ) ;
return ;
}
}
if ( has_skill ( u , SK_MAGIC ) ) {
sc_mage * mage ;
if ( count_skill ( u2 - > faction , SK_MAGIC ) + u - > number >
skill_limit ( u2 - > faction , SK_MAGIC ) ) {
cmistake ( u , ord , 155 , MSG_COMMERCE ) ;
return ;
}
mage = get_mage ( u ) ;
if ( ! mage | | u2 - > faction - > magiegebiet ! = mage - > magietyp ) {
cmistake ( u , ord , 157 , MSG_COMMERCE ) ;
return ;
}
}
if ( has_skill ( u , SK_ALCHEMY )
& & count_skill ( u2 - > faction , SK_ALCHEMY ) + u - > number >
skill_limit ( u2 - > faction , SK_ALCHEMY ) ) {
cmistake ( u , ord , 156 , MSG_COMMERCE ) ;
return ;
}
2015-06-08 09:06:20 +02:00
add_give ( u , u2 , u - > number , u - > number , get_resourcetype ( R_PERSON ) , ord , 0 ) ;
2014-08-08 01:03:46 +02:00
u_setfaction ( u , u2 - > faction ) ;
2015-06-08 09:06:20 +02:00
u2 - > faction - > newbies + = u - > number ;
2010-08-08 10:06:34 +02:00
}
2014-11-03 08:40:58 +01:00
2014-12-12 20:53:39 +01:00
bool can_give_to ( unit * u , unit * u2 ) {
2015-07-06 19:53:09 +02:00
/* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */
2014-12-14 15:23:28 +01:00
if ( ! u2 ) {
2014-12-12 20:53:39 +01:00
return false ;
}
if ( u2 & & ! alliedunit ( u2 , u - > faction , HELP_GIVE )
& & ! cansee ( u - > faction , u - > region , u2 , 0 ) & & ! ucontact ( u2 , u )
& & ! fval ( u2 , UFL_TAKEALL ) ) {
return false ;
}
return true ;
}
2014-11-03 08:40:58 +01:00
void give_cmd ( unit * u , order * ord )
{
2014-12-22 16:28:17 +01:00
char token [ 128 ] ;
2014-11-03 08:40:58 +01:00
region * r = u - > region ;
unit * u2 ;
const char * s ;
2014-12-12 20:53:39 +01:00
int err , n ;
2014-11-03 08:40:58 +01:00
const item_type * itype ;
param_t p ;
plane * pl ;
message * msg ;
keyword_t kwd ;
kwd = init_order ( ord ) ;
assert ( kwd = = K_GIVE ) ;
2014-12-12 20:53:39 +01:00
err = getunit ( r , u - > faction , & u2 ) ;
2014-12-22 16:28:17 +01:00
s = gettoken ( token , sizeof ( token ) ) ;
2014-11-03 08:40:58 +01:00
n = s ? atoip ( s ) : 0 ;
p = ( n > 0 ) ? NOPARAM : findparam ( s , u - > faction - > locale ) ;
/* first, do all the ones that do not require HELP_GIVE or CONTACT */
if ( p = = P_CONTROL ) {
/* handled in give_control_cmd */
return ;
}
2014-12-12 20:53:39 +01:00
if ( err = = GET_NOTFOUND | | ( err ! = GET_PEASANTS & & ! can_give_to ( u , u2 ) ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " feedback_unit_not_found " , " " ) ) ;
return ;
}
if ( u = = u2 ) {
cmistake ( u , ord , 8 , MSG_COMMERCE ) ;
2014-11-03 08:40:58 +01:00
return ;
}
msg = check_give ( u , u2 , ord ) ;
if ( msg ) {
ADDMSG ( & u - > faction - > msgs , msg ) ;
return ;
}
/* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht
* wirklich einfach . */
pl = rplane ( r ) ;
if ( pl & & fval ( pl , PFL_NOGIVE ) & & ( ! u2 | | ! fval ( u2 , UFL_TAKEALL ) ) ) {
cmistake ( u , ord , 268 , MSG_COMMERCE ) ;
return ;
}
if ( u2 & & u_race ( u2 ) = = get_race ( RC_SPELL ) ) {
ADDMSG ( & u - > faction - > msgs , msg_feedback ( u , ord , " feedback_unit_not_found " ,
" " ) ) ;
return ;
}
else if ( u2 & & ! alliedunit ( u2 , u - > faction , HELP_GIVE ) & & ! ucontact ( u2 , u ) ) {
cmistake ( u , ord , 40 , MSG_COMMERCE ) ;
return ;
}
else if ( p = = P_HERBS ) {
bool given = false ;
2015-04-19 12:49:39 +02:00
if ( ( u_race ( u ) - > ec_flags & ECF_KEEP_ITEM ) & & u2 ! = NULL ) {
2014-11-03 08:40:58 +01:00
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_nogive " , " race " , u_race ( u ) ) ) ;
return ;
}
if ( ! can_give ( u , u2 , NULL , GIVE_HERBS ) ) {
feedback_give_not_allowed ( u , ord ) ;
return ;
}
if ( u2 & & ! ( u_race ( u2 ) - > ec_flags & GETITEM ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_notake " , " race " , u_race ( u2 ) ) ) ;
return ;
}
if ( u - > items ) {
item * * itmp = & u - > items ;
while ( * itmp ) {
item * itm = * itmp ;
const item_type * itype = itm - > type ;
if ( fval ( itype , ITF_HERB ) & & itm - > number > 0 ) {
2015-07-06 19:53:09 +02:00
/* give_item ändert im fall,das man alles übergibt, die
2014-11-03 08:40:58 +01:00
* item - liste der unit , darum continue vor pointerumsetzten */
if ( give_item ( itm - > number , itm - > type , u , u2 , ord ) = = 0 ) {
given = true ;
if ( * itmp ! = itm )
continue ;
continue ;
}
}
itmp = & itm - > next ;
}
}
2014-12-12 20:53:39 +01:00
if ( ! given ) {
2014-11-03 08:40:58 +01:00
cmistake ( u , ord , 38 , MSG_COMMERCE ) ;
2014-12-12 20:53:39 +01:00
}
2014-11-03 08:40:58 +01:00
return ;
}
else if ( p = = P_ZAUBER ) {
cmistake ( u , ord , 7 , MSG_COMMERCE ) ;
/* geht nimmer */
return ;
}
else if ( p = = P_UNIT ) { /* Einheiten uebergeben */
if ( ! ( u_race ( u ) - > ec_flags & GIVEUNIT ) ) {
cmistake ( u , ord , 167 , MSG_COMMERCE ) ;
return ;
}
give_unit ( u , u2 , ord ) ;
return ;
}
else if ( p = = P_ANY ) {
const char * s ;
if ( ! can_give ( u , u2 , NULL , GIVE_ALLITEMS ) ) {
feedback_give_not_allowed ( u , ord ) ;
return ;
}
2014-12-22 16:28:17 +01:00
s = gettoken ( token , sizeof ( token ) ) ;
2014-11-03 08:40:58 +01:00
if ( ! s | | * s = = 0 ) { /* GIVE ALL items that you have */
/* do these checks once, not for each item we have: */
2015-04-19 12:49:39 +02:00
if ( ( u_race ( u ) - > ec_flags & ECF_KEEP_ITEM ) & & u2 ! = NULL ) {
2014-11-03 08:40:58 +01:00
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_nogive " , " race " , u_race ( u ) ) ) ;
return ;
}
if ( u2 & & ! ( u_race ( u2 ) - > ec_flags & GETITEM ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_notake " , " race " , u_race ( u2 ) ) ) ;
return ;
}
2015-07-06 19:53:09 +02:00
/* für alle items einmal prüfen, ob wir mehr als von diesem Typ
* reserviert ist besitzen und diesen Teil dann ü bergeben */
2014-11-03 08:40:58 +01:00
if ( u - > items ) {
item * * itmp = & u - > items ;
while ( * itmp ) {
item * itm = * itmp ;
const item_type * itype = itm - > type ;
if ( itm - > number > 0
2014-12-12 11:28:37 +01:00
& & itm - > number - get_reservation ( u , itype ) > 0 ) {
n = itm - > number - get_reservation ( u , itype ) ;
2014-11-03 08:40:58 +01:00
if ( give_item ( n , itype , u , u2 , ord ) = = 0 ) {
if ( * itmp ! = itm )
continue ;
}
}
itmp = & itm - > next ;
}
}
}
else {
if ( isparam ( s , u - > faction - > locale , P_PERSON ) ) {
if ( ! ( u_race ( u ) - > ec_flags & GIVEPERSON ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_noregroup " , " race " , u_race ( u ) ) ) ;
}
else {
2014-12-10 21:17:00 +01:00
message * msg ;
2014-12-11 08:35:05 +01:00
msg = u2 ? give_men ( u - > number , u , u2 , ord ) : disband_men ( u - > number , u , ord ) ;
2014-12-10 21:17:00 +01:00
if ( msg ) {
ADDMSG ( & u - > faction - > msgs , msg ) ;
}
2014-11-03 08:40:58 +01:00
}
}
2015-04-19 12:49:39 +02:00
else if ( ( u_race ( u ) - > ec_flags & ECF_KEEP_ITEM ) & & u2 ! = NULL ) {
2014-11-03 08:40:58 +01:00
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_nogive " , " race " , u_race ( u ) ) ) ;
}
else if ( u2 & & ! ( u_race ( u2 ) - > ec_flags & GETITEM ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_notake " , " race " , u_race ( u2 ) ) ) ;
}
else {
itype = finditemtype ( s , u - > faction - > locale ) ;
if ( itype ! = NULL ) {
item * i = * i_find ( & u - > items , itype ) ;
if ( i ! = NULL ) {
if ( can_give ( u , u2 , itype , 0 ) ) {
2014-12-12 11:28:37 +01:00
n = i - > number - get_reservation ( u , itype ) ;
2014-11-03 08:40:58 +01:00
give_item ( n , itype , u , u2 , ord ) ;
}
else {
feedback_give_not_allowed ( u , ord ) ;
}
}
}
}
}
return ;
}
else if ( p = = P_EACH ) {
if ( u2 = = NULL ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " peasants_give_invalid " , " " ) ) ;
return ;
}
2014-12-22 16:28:17 +01:00
s = gettoken ( token , sizeof ( token ) ) ; /* skip one ahead to get the amount. */
n = s ? atoip ( s ) : 0 ; /* n: Anzahl */
2014-11-03 08:40:58 +01:00
n * = u2 - > number ;
}
2014-12-22 16:28:17 +01:00
s = gettoken ( token , sizeof ( token ) ) ;
2014-11-03 08:40:58 +01:00
if ( s = = NULL ) {
cmistake ( u , ord , 113 , MSG_COMMERCE ) ;
return ;
}
if ( isparam ( s , u - > faction - > locale , P_PERSON ) ) {
2014-12-10 21:17:00 +01:00
message * msg ;
2014-11-03 08:40:58 +01:00
if ( ! ( u_race ( u ) - > ec_flags & GIVEPERSON ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_noregroup " , " race " , u_race ( u ) ) ) ;
return ;
}
2014-12-14 06:02:08 +01:00
n = _min ( u - > number , n ) ;
2014-12-12 13:32:21 +01:00
msg = u2 ? give_men ( n , u , u2 , ord ) : disband_men ( n , u , ord ) ;
2014-12-10 21:17:00 +01:00
if ( msg ) {
ADDMSG ( & u - > faction - > msgs , msg ) ;
}
2014-11-03 08:40:58 +01:00
return ;
}
if ( u2 ! = NULL ) {
2015-04-19 12:49:39 +02:00
if ( ( u_race ( u ) - > ec_flags & ECF_KEEP_ITEM ) & & u2 ! = NULL ) {
2014-11-03 08:40:58 +01:00
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_nogive " , " race " , u_race ( u ) ) ) ;
return ;
}
if ( ! ( u_race ( u2 ) - > ec_flags & GETITEM ) ) {
ADDMSG ( & u - > faction - > msgs ,
msg_feedback ( u , ord , " race_notake " , " race " , u_race ( u2 ) ) ) ;
return ;
}
}
itype = finditemtype ( s , u - > faction - > locale ) ;
if ( itype ! = NULL ) {
if ( can_give ( u , u2 , itype , 0 ) ) {
give_item ( n , itype , u , u2 , ord ) ;
}
else {
feedback_give_not_allowed ( u , ord ) ;
}
return ;
}
cmistake ( u , ord , 123 , MSG_COMMERCE ) ;
}
message * check_give ( const unit * u , const unit * u2 , order * ord ) {
if ( ! can_give ( u , u2 , NULL , GIVE_ALLITEMS ) ) {
return msg_feedback ( u , ord , " feedback_give_forbidden " , " " ) ;
}
return 0 ;
}