ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/apply.C
(Generate patch)

Comparing deliantra/server/server/apply.C (file contents):
Revision 1.67 by root, Thu Feb 8 03:09:32 2007 UTC vs.
Revision 1.68 by root, Sat Feb 10 01:52:29 2007 UTC

1015 * Handle apply on containers. 1015 * Handle apply on containers.
1016 * By Eneq(@csd.uu.se). 1016 * By Eneq(@csd.uu.se).
1017 * Moved to own function and added many features [Tero.Haatanen@lut.fi] 1017 * Moved to own function and added many features [Tero.Haatanen@lut.fi]
1018 * added the alchemical cauldron to the code -b.t. 1018 * added the alchemical cauldron to the code -b.t.
1019 */ 1019 */
1020
1021int 1020int
1022apply_container (object *op, object *sack) 1021apply_container (object *op, object *sack)
1023{ 1022{
1024 char buf[MAX_BUF]; 1023 if (op->type != PLAYER || !op->contr->ns)
1025 object *tmp;
1026
1027 if (op->type != PLAYER)
1028 return 0; /* This might change */ 1024 return 0; /* This might change */
1029 1025
1030 if (sack == NULL || sack->type != CONTAINER) 1026 if (!sack || sack->type != CONTAINER)
1031 { 1027 {
1032 LOG (llevError, "apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]"); 1028 LOG (llevError, "apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]");
1033 return 0; 1029 return 0;
1034 } 1030 }
1035 1031
1036 op->contr->last_used = 0; 1032 op->contr->last_used = 0;
1037 1033
1038 if (sack->env != op) 1034 if (sack->env && sack->env != op)
1035 {
1036 new_draw_info (NDI_UNIQUE, 0, op, "You must put it onto the floor or into your inventory first.");
1037 return 1;
1039 { 1038 }
1040 if (sack->other_arch == NULL || sack->env != NULL) 1039
1040 // already applied == open on ground, or open in inv, or active in inv
1041 if (sack->flag [FLAG_APPLIED])
1042 {
1043 if (op->container == sack)
1041 { 1044 {
1042 new_draw_info (NDI_UNIQUE, 0, op, "You must get it first."); 1045 // open on ground or inv, so close
1046 op->close_container ();
1043 return 1; 1047 return 1;
1044 } 1048 }
1045 1049 else if (!sack->env)
1046 /* It's on the ground, the problems begin */
1047 if (op->container != sack)
1048 {
1049 /* it's closed OR some player has opened it */
1050 if (QUERY_FLAG (sack, FLAG_APPLIED))
1051 { 1050 {
1052 for (tmp = GET_MAP_OB (sack->map, sack->x, sack->y); tmp && tmp->container != sack; tmp = tmp->above); 1051 // active, but not ours: some other player has opened it
1053 if (tmp)
1054 {
1055 /* some other player have opened it */
1056 new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack)); 1052 new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack));
1057 return 1; 1053 return 1;
1058 }
1059 }
1060 }
1061 if (QUERY_FLAG (sack, FLAG_APPLIED))
1062 { 1054 }
1063 if (op->container == NULL)
1064 {
1065 tmp = arch_to_object (sack->other_arch);
1066 /* not good, but insert_ob_in_ob() is too smart */
1067 CLEAR_FLAG (tmp, FLAG_REMOVED);
1068 tmp->x = tmp->y = 0;
1069 tmp->map = NULL;
1070 tmp->env = sack;
1071 if (sack->inv)
1072 sack->inv->above = tmp;
1073 tmp->below = sack->inv;
1074 tmp->above = NULL;
1075 sack->inv = tmp;
1076 sack->move_off = MOVE_ALL; /* trying force closing it */
1077 }
1078 else
1079 {
1080 sack->move_off = 0;
1081 tmp = sack->inv;
1082 1055
1083 if (tmp && tmp->type == CLOSE_CON) 1056 // fall through to opening it (active in inv)
1084 tmp->destroy ();
1085 }
1086 }
1087 }
1088
1089 if (QUERY_FLAG (sack, FLAG_APPLIED))
1090 { 1057 }
1058 else if (sack->env)
1059 {
1060 // it is in our env, so activate it, do not open yet
1091 if (op->container) 1061 op->close_container ();
1092 { 1062 sack->flag [FLAG_APPLIED] = 1;
1093 if (op->container != sack) 1063 esrv_update_item (UPD_FLAGS, op, sack);
1094 { 1064 return 1;
1095 tmp = op->container; 1065 }
1096 apply_container (op, tmp); 1066
1097 sprintf (buf, "You close %s and open ", query_name (tmp)); 1067 // it's locked?
1098 op->container = sack; 1068 if (sack->slaying)
1099 strcat (buf, query_name (sack)); 1069 {
1100 strcat (buf, "."); 1070 if (object *tmp = find_key (op, op, sack))
1101 } 1071 new_draw_info_format (NDI_UNIQUE, 0, op, "You unlock %s with %s.", query_name (sack), query_name (tmp));
1102 else
1103 {
1104 CLEAR_FLAG (sack, FLAG_APPLIED);
1105 op->container = NULL;
1106 sprintf (buf, "You close %s.", query_name (sack));
1107 }
1108 }
1109 else 1072 else
1110 { 1073 {
1111 CLEAR_FLAG (sack, FLAG_APPLIED);
1112 sprintf (buf, "You open %s.", query_name (sack));
1113 SET_FLAG (sack, FLAG_APPLIED);
1114 op->container = sack;
1115 }
1116 }
1117 else
1118 { /* not applied */
1119 if (sack->slaying)
1120 { /* it's locked */
1121 tmp = find_key (op, op, sack);
1122 if (tmp)
1123 {
1124 sprintf (buf, "You unlock %s with %s.", query_name (sack), query_name (tmp));
1125 SET_FLAG (sack, FLAG_APPLIED);
1126
1127 if (sack->env == NULL)
1128 { /* if it's on ground,open it also */
1129 new_draw_info (NDI_UNIQUE, 0, op, buf);
1130 apply_container (op, sack);
1131 return 1;
1132 }
1133 }
1134 else
1135 sprintf (buf, "You don't have the key to unlock %s.", query_name (sack)); 1074 new_draw_info_format (NDI_UNIQUE, 0, op, "You don't have the key to unlock %s.", query_name (sack));
1136 }
1137 else
1138 {
1139 sprintf (buf, "You readied %s.", query_name (sack));
1140 SET_FLAG (sack, FLAG_APPLIED);
1141
1142 if (sack->env == NULL)
1143 { /* if it's on ground,open it also */
1144 new_draw_info (NDI_UNIQUE, 0, op, buf);
1145 apply_container (op, sack);
1146 return 1; 1075 return 1;
1147 } 1076 }
1148 }
1149 } 1077 }
1150 1078
1151 new_draw_info (NDI_UNIQUE, 0, op, buf); 1079 op->open_container (sack);
1152
1153 if (op->contr)
1154 op->contr->ns->floorbox_update ();
1155 1080
1156 return 1; 1081 return 1;
1157} 1082}
1158
1159/**
1160 * Eneq(@csd.uu.se): Handle apply on containers. This is for containers
1161 * the player has in their inventory, eg, sacks, luggages, etc.
1162 *
1163 * Moved to own function and added many features [Tero.Haatanen@lut.fi]
1164 * This version is for client/server mode.
1165 * op is the player, sack is the container the player is opening or closing.
1166 * return 1 if an object is apllied somehow or another, 0 if error/no apply
1167 *
1168 * Reminder - there are three states for any container - closed (non applied),
1169 * applied (not open, but objects that match get tossed into it), and open
1170 * (applied flag set, and op->container points to the open container)
1171 */
1172
1173int
1174esrv_apply_container (object *op, object *sack)
1175{
1176 object *tmp = op->container;
1177
1178 if (op->type != PLAYER)
1179 return 0; /* This might change */
1180
1181 if (sack == NULL || sack->type != CONTAINER)
1182 {
1183 LOG (llevError, "esrv_apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]");
1184 return 0;
1185 }
1186
1187 /* If we have a currently open container, then it needs to be closed in all cases
1188 * if we are opening this one up. We then fall through if appropriate for
1189 * openening the new container.
1190 */
1191
1192 if (op->container && QUERY_FLAG (sack, FLAG_APPLIED))
1193 {
1194 if (op->container->env != op)
1195 { /* if container is on the ground */
1196 op->container->move_off = 0;
1197 }
1198
1199 if (INVOKE_OBJECT (CLOSE, tmp, ARG_OBJECT (op)))
1200 return 1;
1201
1202 new_draw_info_format (NDI_UNIQUE, 0, op, "You close %s.", query_name (op->container));
1203 CLEAR_FLAG (op->container, FLAG_APPLIED);
1204 op->container = NULL;
1205 esrv_update_item (UPD_FLAGS, op, tmp);
1206 if (tmp == sack)
1207 return 1;
1208 }
1209
1210
1211 /* If the player is trying to open it (which he must be doing if we got here),
1212 * and it is locked, check to see if player has the equipment to open it.
1213 */
1214
1215 if (sack->slaying)
1216 { /* it's locked */
1217 tmp = find_key (op, op, sack);
1218 if (tmp)
1219 {
1220 new_draw_info_format (NDI_UNIQUE, 0, op, "You unlock %s with %s.", query_name (sack), query_name (tmp));
1221 }
1222 else
1223 {
1224 new_draw_info_format (NDI_UNIQUE, 0, op, "You don't have the key to unlock %s.", query_name (sack));
1225 return 0;
1226 }
1227 }
1228
1229 /* By the time we get here, we have made sure any other container has been closed and
1230 * if this is a locked container, the player they key to open it.
1231 */
1232
1233 /* There are really two cases - the sack is either on the ground, or the sack is
1234 * part of the players inventory. If on the ground, we assume that the player is
1235 * opening it, since if it was being closed, that would have been taken care of above.
1236 */
1237
1238
1239 if (sack->env != op)
1240 {
1241 /* Hypothetical case - the player is trying to open a sack that belong to someone
1242 * else. This normally should not happen, but a misbehaving client/player could
1243 * try to do it, so lets handle it gracefully.
1244 */
1245 if (sack->env)
1246 {
1247 new_draw_info_format (NDI_UNIQUE, 0, op, "You can't open %s", query_name (sack));
1248 return 0;
1249 }
1250 /* set these so when the player walks off, we can unapply the sack */
1251 sack->move_off = MOVE_ALL; /* trying force closing it */
1252
1253 CLEAR_FLAG (sack, FLAG_APPLIED);
1254 new_draw_info_format (NDI_UNIQUE, 0, op, "You open %s.", query_name (sack));
1255 SET_FLAG (sack, FLAG_APPLIED);
1256 op->container = sack;
1257 esrv_update_item (UPD_FLAGS, op, sack);
1258 esrv_send_inventory (op, sack);
1259
1260 }
1261 else
1262 { /* sack is in players inventory */
1263 if (QUERY_FLAG (sack, FLAG_APPLIED))
1264 { /* readied sack becoming open */
1265 CLEAR_FLAG (sack, FLAG_APPLIED);
1266 new_draw_info_format (NDI_UNIQUE, 0, op, "You open %s.", query_name (sack));
1267 SET_FLAG (sack, FLAG_APPLIED);
1268 op->container = sack;
1269 esrv_update_item (UPD_FLAGS, op, sack);
1270 esrv_send_inventory (op, sack);
1271 }
1272 else
1273 {
1274 CLEAR_FLAG (sack, FLAG_APPLIED);
1275 new_draw_info_format (NDI_UNIQUE, 0, op, "You readied %s.", query_name (sack));
1276 SET_FLAG (sack, FLAG_APPLIED);
1277 esrv_update_item (UPD_FLAGS, op, sack);
1278 }
1279 }
1280 return 1;
1281}
1282
1283 1083
1284/** 1084/**
1285 * Handles dropping things on altar. 1085 * Handles dropping things on altar.
1286 * Returns true if sacrifice was accepted. 1086 * Returns true if sacrifice was accepted.
1287 */ 1087 */
1700 1500
1701 apply_sign (victim, trap, 1); 1501 apply_sign (victim, trap, 1);
1702 goto leave; 1502 goto leave;
1703 1503
1704 case CONTAINER: 1504 case CONTAINER:
1705 if (victim->type == PLAYER)
1706 (void) esrv_apply_container (victim, trap);
1707 else
1708 (void) apply_container (victim, trap); 1505 apply_container (victim, trap);
1709 goto leave; 1506 goto leave;
1710 1507
1711 case RUNE: 1508 case RUNE:
1712 case TRAP: 1509 case TRAP:
1713 if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) 1510 if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE))
2610 case POTION: 2407 case POTION:
2611 (void) apply_potion (op, tmp); 2408 (void) apply_potion (op, tmp);
2612 return 1; 2409 return 1;
2613 2410
2614 /* Eneq(@csd.uu.se): Handle apply on containers. */ 2411 /* Eneq(@csd.uu.se): Handle apply on containers. */
2412 //TODO: remove, as it is unsed?
2615 case CLOSE_CON: 2413 case CLOSE_CON:
2616 if (op->type == PLAYER)
2617 (void) esrv_apply_container (op, tmp->env);
2618 else
2619 (void) apply_container (op, tmp->env); 2414 apply_container (op, tmp->env);
2620 return 1; 2415 return 1;
2621 2416
2622 case CONTAINER: 2417 case CONTAINER:
2623 if (op->type == PLAYER)
2624 (void) esrv_apply_container (op, tmp);
2625 else
2626 (void) apply_container (op, tmp); 2418 apply_container (op, tmp);
2627 return 1; 2419 return 1;
2628 2420
2629 case TREASURE: 2421 case TREASURE:
2630 if (op->type == PLAYER) 2422 if (op->type == PLAYER)
2631 { 2423 {
2632 apply_treasure (op, tmp); 2424 apply_treasure (op, tmp);
2633 return 1; 2425 return 1;
2634 } 2426 }
2635 else 2427 else
2636 {
2637 return 0; 2428 return 0;
2638 }
2639 2429
2640 case WEAPON: 2430 case WEAPON:
2641 case ARMOUR: 2431 case ARMOUR:
2642 case BOOTS: 2432 case BOOTS:
2643 case GLOVES: 2433 case GLOVES:
2795 */ 2585 */
2796 2586
2797void 2587void
2798player_apply_below (object *pl) 2588player_apply_below (object *pl)
2799{ 2589{
2800 object *tmp, *next;
2801 int floors; 2590 int floors = 0;
2802 2591
2803 /* If using a container, set the starting item to be the top 2592 /* If using a container, set the starting item to be the top
2804 * item in the container. Otherwise, use the map. 2593 * item in the container. Otherwise, use the map.
2805 */
2806 tmp = (pl->container != NULL) ? pl->container->inv : pl->below;
2807
2808 /* This is perhaps more complicated. However, I want to make sure that 2594 * This is perhaps more complicated. However, I want to make sure that
2809 * we don't use a corrupt pointer for the next object, so we get the 2595 * we don't use a corrupt pointer for the next object, so we get the
2810 * next object in the stack before applying. This is can only be a 2596 * next object in the stack before applying. This is can only be a
2811 * problem if player_apply() has a bug in that it uses the object but does 2597 * problem if player_apply() has a bug in that it uses the object but does
2812 * not return a proper value. 2598 * not return a proper value.
2813 */ 2599 */
2814 for (floors = 0; tmp != NULL; tmp = next) 2600 for (object *next, *tmp = pl->container ? pl->container->inv : pl->below; tmp; tmp = next)
2815 { 2601 {
2816 next = tmp->below; 2602 next = tmp->below;
2603
2817 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 2604 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
2818 floors++; 2605 floors++;
2819 else if (floors > 0) 2606 else if (floors > 0)
2820 return; /* process only floor objects after first floor object */ 2607 return; /* process only floor objects after first floor object */
2821 2608
3677 } 3464 }
3678 return tmp ? 1 : 0; 3465 return tmp ? 1 : 0;
3679} 3466}
3680 3467
3681/** 3468/**
3682 * fix_auto_apply goes through the entire map (only the first time 3469 * fix_auto_apply goes through the entire map every time a map
3683 * when an original map is loaded) and performs special actions for 3470 * is loaded or swapped in and performs special actions for
3684 * certain objects (most initialization of chests and creation of 3471 * certain objects (most initialization of chests and creation of
3685 * treasures and stuff). Calls auto_apply if appropriate. 3472 * treasures and stuff). Calls auto_apply if appropriate.
3686 */ 3473 */
3687void 3474void
3688maptile::fix_auto_apply () 3475maptile::fix_auto_apply ()
3765 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ()) 3552 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ())
3766 { 3553 {
3767 create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0); 3554 create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0);
3768 tmp->randomitems = NULL; 3555 tmp->randomitems = NULL;
3769 } 3556 }
3557 // close all containers
3558 else if (tmp->type == CONTAINER)
3559 tmp->flag [FLAG_APPLIED] = 0;
3770 3560
3771 tmp = above; 3561 tmp = above;
3772 } 3562 }
3773 3563
3774 for (mapspace *ms = spaces + size (); ms-- > spaces; ) 3564 for (mapspace *ms = spaces + size (); ms-- > spaces; )

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines