// marriage npc
// allows to marry other players
// * must be duplicated
- script marriage NPC_NO_SPRITE,{
end;
function toPlayer {
// send a message to the player
.previous = playerattached();
// attachrid is required because we want to use l() on another player
attachrid(getarg(1, getcharid(CHAR_ID_ACCOUNT)));
dispbottom(b(l(getarg(0))));
attachrid(.previous);
return;
}
function _officiator {
// make the wedding officiator say a message
if (getarg(1, 0)) {
// only send to the target player
unittalk(.officiator, l(getarg(0)), true, SELF, getarg(1, getcharid(CHAR_ID_ACCOUNT)));
} else {
// regular npctalk
unittalk(.officiator, getarg(0), true);
}
return;
}
function officiator {
if (.officiator) {
return _officiator(getarg(0));
} else {
toPlayer(getarg(0));
if (getarg(1, 0)) {
toPlayer(getarg(0), getarg(1));
}
return;
}
}
function explain {
// send an explanation message
if (.officiator) {
return _officiator(getarg(0), playerattached());
} else {
return toPlayer(getarg(0));
}
}
function do_marriage {
if (.officiator) {
// let the officiator handle it
@marriage$ = getarg(0);
doevent(.officiator$ + "::OnDoMarriage");
} else {
// no officiator
marriage(getarg(0));
announce(sprintf("%s and %s are now married!", strcharinfo(PC_NAME), getarg(0)), bc_all);
}
return;
}
OnCheckWord:
.@verb$ = strtolower($@p1$);
if (.@verb$ != "marry" && .@verb$ != l("marry")) {
end; // ignore
}
// get the location of the invoking character
getmapxy(.@map$, .@x, .@y, UNITTYPE_PC);
if (.@map$ != .map$ || .@x < .x1 || .@x > .x2 || .@y < .y1 || .@y > .y2) {
explain("You must stand in the designated area");
end;
}
// check if the target character exists and is online
.@target$ = $@p2$;
.@target = getcharid(CHAR_ID_ACCOUNT, .@target$);
if (.@target == 0) {
explain(sprintf("Player %s doesn't exist or is offline", .@target$));
end;
}
if (.@target == playerattached()) {
explain("You cannot marry yourself");
end;
}
// get the location of the target character
getmapxy(.@map$, .@x, .@y, UNITTYPE_PC, .@target);
if (.@map$ != .map$ || .@x < .x1 || .@x > .x2 || .@y < .y1 || .@y > .y2) {
explain("Your partner must stand in the designated area");
end;
}
if (BaseLevel < WEDDING_MIN_LEVEL || readparam(BaseLevel, .@target) < WEDDING_MIN_LEVEL) {
explain(sprintf("You and your partner must be at least level %i to marry", WEDDING_MIN_LEVEL));
end;
}
// XXX: do we want to check for wedding rings?
if (!isequipped(WeddingRing)) {
explain("You must be wearing a %s to marry.", getitemname(WeddingRing));
end;
}
if (getpartnerid()) {
if (getpartnerid() == getcharid(CHAR_ID_CHAR, .@target$)) {
explain("You are already married to this person.");
} else {
explain("You are already married to someone else.");
}
end;
}
if (getvariableofpc(@marriage, .@target, 0) == getcharid(CHAR_ID_CHAR)) {
// the target already requested to marry us
if (getvariableofpc(@marriage[1], .@target, 0) > now()) {
// You must be wearing a wedding ring at all times
if (!isequipped(WeddingRing)) {
explain("You must be wearing a %s to marry.", getitemname(WeddingRing));
end;
}
// marriage request has not expired: procceed to marry
do_marriage(.@target$);
end;
} else {
// marriage request expired
explain("This marriage proposal has expired. Please try again");
// refresh our own expiration
@marriage = getcharid(CHAR_ID_CHAR, .@target$);
@marriage[1] = time_from_minutes(+15); // expiration
}
} else if (@marriage && @marriage[1] > now()) {
// we already initiated a marriage request
if (@marriage == getcharid(CHAR_ID_CHAR, .@target$)) {
explain("You are already marrying this person.");
@marriage[1] = time_from_minutes(+15); // refresh expiration
} else {
// already marrying someone else?
explain("You are already in the process of marrying someone else.");
explain(sprintf("Are you sure you wish to marry %s?", .@target$));
explain(sprintf("To confirm, type the same message again: %s %s", $@p1$, $@p2$));
@marriage = 0; // clear the current target
}
} else {
// initiate a new marriage request
@marriage = getcharid(CHAR_ID_CHAR, .@target$);
@marriage[1] = time_from_minutes(+15); // expiration
announce(sprintf("%s is asking %s for marriage!", strcharinfo(PC_NAME), .@target$), bc_all);
officiator(sprintf("%s, to accept this marriage proposal, say: marry %s", .@target$, strcharinfo(PC_NAME)), .@target);
}
end;
OnInit:
if (strnpcinfo(NPC_MAP) == "") {
// this is not a duplicate
end;
}
explode(.@hidden$, strnpcinfo(NPC_NAME_HIDDEN), "#");
explode(.@area$, .@hidden$[getarraysize(.@hidden$) - 1], ",");
switch (getarraysize(.@area$)) {
case 1:
if (.@area$[0] == "") {
.@d = 3;
} else {
.@d = atoi(.@area$[0]);
}
.x1 = .x - .@d; .x2 = .x + .@d;
.y1 = .y - .@d; .y2 = .y + .@d;
break;
case 2:
.@dx = atoi(.@area$[0]); .@dy = atoi(.@area$[1]);
.x1 = .x - .@dx; .x2 = .x + .@dx;
.y1 = .y - .@dy; .y2 = .y + .@dy;
break;
case 4:
.x1 = atoi(.@area$[0]); .x2 = atoi(.@area$[2]);
.y1 = atoi(.@area$[1]); .y2 = atoi(.@area$[3]);
break;
default:
consolemes(CONSOLEMES_ERROR, "unexpected number of arguments for the marriage duplicate");
break;
}
// now find the wedding officiator (if any)
.@count = getunits(BL_NPC, .@units, false, strnpcinfo(NPC_MAP));
freeloop(true);
for (.@i = 0; .@i < .@count; ++.@i) {
.@name$ = strtolower(strnpcinfo(NPC_NAME_HIDDEN, "", .@units[.@i]));
.@full$ = strnpcinfo(NPC_NAME, "", .@units[.@i]);
if (getnpcsubtype(.@units[.@i]) != NPCSUBTYPE_SCRIPT) {
// getunits() doesn't filter npc subtypes
continue;
}
if (endswith(.@name$, "officiator") ||
endswith(.@name$, "marriage") ||
endswith(.@name$, "wedding") ||
getvariableofnpc(.officiator, .@full$) ||
getvariableofnpc(.marriage, .@full$) ||
getvariableofnpc(.wedding, .@full$)) {
.officiator = .@units[.@i];
.officiator$ = .@full$;
break;
}
}
freeloop(false);
defpattern(.id, "^.+ : (?:##[0-9aBb])?([A-Za-z]+) (.{4,23})$", "OnCheckWord");
activatepset(.id);
.distance = 14;
end;
}
// to use, create a duplicate:
//001-1,30,31,0 duplicate(marriage) name#x1,y1,x2,y2 NPCID
//001-1,30,31,0 duplicate(marriage) name#range NPCID