2

I'm trying to create a command that will allow me to create multiple item for a game. My main problem comes from re-usability of that command. The fact that I have more than 9 arguments for some of them makes me go to key_define. I also looked at property but I have hard time finding usable documentation on how to use it adequately, so I stayed to key-values instead.

Globally, what my code do is creating a lot of shortcuts to be able to put in my document later on. Let's say that I create these two characters:

\createCharacter{Barry}<main>[lastname=Allen, prof=scientist]{39}

and

\createCharacter*{Jessy}<side>[lastname=Quick, nickname=Jess, prof=professional runner]{24}

When I call \mainFName I get "Barry" and \sideFName I get "Jessy", as intended, but when I call \sideLName I get "Quick" and \mainLName I get "Quick" as well. So what is happening is that instead of taking the value at the moment of the creation, it reevaluated it's "current value" (which is the last character created).

So here is the code I want to correct and make working without having to create all the tl_new for each character, and eventually every item, magic, and whatever else may come handy. If I was able to do withing my \createCharacter something like \tl_new:c {\l_#4_firstname_tl} It would be perfect.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       CHARACTER MAKER
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ExplSyntaxOn

% Define Special
\tl_new:N  \l_character_firstname_tl
\tl_new:N  \l_character_lastname_tl
\tl_new:N  \l_character_title_tl
\tl_new:N  \l_character_profession_tl
\tl_new:N  \l_character_noblesse_tl
\tl_new:N  \l_character_class_tl
\tl_new:N  \l_character_nick_tl

\int_new:N \l_character_age_int


\keys_define:nn { Character/Identity } {
%   firsname .tl_set:N = \l_character_firstname_tl,
    lastname .tl_set:N = \l_character_lastname_tl,
    title    .tl_set:N = \l_character_title_tl,
    prof     .tl_set:N = \l_character_profession_tl,
    noble    .tl_set:N = \l_character_noblesse_tl,
    class    .tl_set:N = \l_character_class_tl,
    race     .tl_set:N = \l_character_race_tl,
    nickname .tl_set:N = \l_character_nick_tl,
%   age      .int_set:N = \l_character_age_int
%   , unknown  .code:n = {}
}

\NewDocumentCommand{\createCharacter}{s t- m D<>{#3} o m}{

    \IfValueT{#5}{\keys_set:nn{Character/Identity}{#5}}

    \exp_args:Nc \NewDocumentCommand { #4 FName } {}{ #3 }
    \exp_args:Nc \NewDocumentCommand { #4 LName } {}{ \l_character_lastname_tl }
    \exp_args:Nc \NewDocumentCommand { #4 Polite } {}{ \use:c { #4 Title } ~ \use:c { #4 LName } }
    \exp_args:Nc \NewDocumentCommand { #4 Sign } {}{ \use:c { #4 FPolite } , ~ \l_character_noblesse_tl }
    \exp_args:Nc \NewDocumentCommand { #4 Age } {}{ #6 }
    \exp_args:Nc \NewDocumentCommand { #4 Prof } {}{ \l_character_profession_tl }
    \exp_args:Nc \NewDocumentCommand { #4 Class } {}{ \l_character_class_tl }
    \exp_args:Nc \NewDocumentCommand { #4 Race } {}{ \l_character_race_tl }
    \exp_args:Nc \NewDocumentCommand { #4 NName } {}{ \l_character_nick_tl }

    %% more code here but irrelevent for the question %%

}


\ExplSyntaxOff

1 Answer 1

2

I wouldn't use \NewDocumentCommand for those macros. The problem is that you're storing the variables, rather than their values.

\documentclass{article}
\usepackage{xparse}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%       CHARACTER MAKER
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\ExplSyntaxOn

% Define Special
\tl_new:N  \l_character_firstname_tl
\tl_new:N  \l_character_lastname_tl
\tl_new:N  \l_character_title_tl
\tl_new:N  \l_character_profession_tl
\tl_new:N  \l_character_noblesse_tl
\tl_new:N  \l_character_class_tl
\tl_new:N  \l_character_nick_tl

\int_new:N \l_character_age_int


\keys_define:nn { Character/Identity } {
%   firstname .tl_set:N = \l_character_firstname_tl,
    lastname .tl_set:N = \l_character_lastname_tl,
    title    .tl_set:N = \l_character_title_tl,
    prof     .tl_set:N = \l_character_profession_tl,
    noble    .tl_set:N = \l_character_noblesse_tl,
    class    .tl_set:N = \l_character_class_tl,
    race     .tl_set:N = \l_character_race_tl,
    nickname .tl_set:N = \l_character_nick_tl,
%   age      .int_set:N = \l_character_age_int
%   , unknown  .code:n = {}
}

\NewDocumentCommand{\createCharacter}{s t- m D<>{#3} o m}
 {
  % we don't want that the unset keys are carried over from the previous ones
  \group_begin:
    \IfValueT{#5}{\keys_set:nn{Character/Identity}{#5}}

    \cs_new_protected:cpn { #4 FName }  { #3 }
    \cs_new_protected:cpx { #4 LName }  { \exp_not:V \l_character_lastname_tl }
    \cs_new_protected:cpx { #4 Title }  { \exp_not:V \l_character_title_tl }
    \cs_new_protected:cpn { #4 Polite } { \use:c { #4 Title } ~ \use:c { #4 LName } }
    \cs_new_protected:cpx { #4 Sign }   { \exp_not:c { #4 FPolite } , ~ \exp_not:V \l_character_noblesse_tl }
    \cs_new_protected:cpn { #4 Age }    { #6 }
    \cs_new_protected:cpx { #4 Prof }   { \exp_not:V \l_character_profession_tl }
    \cs_new_protected:cpx { #4 Class }  { \exp_not:V \l_character_class_tl }
    \cs_new_protected:cpx { #4 Race }   { \exp_not:V \l_character_race_tl }
    \cs_new_protected:cpx { #4 NName }  { \exp_not:V \l_character_nick_tl }
  \group_end:

    %% more code here but irrelevent for the question %%

}

\ExplSyntaxOff

\createCharacter{Barry}<main>[lastname=Allen, prof=scientist]{39}
\createCharacter*{Jessy}<side>[lastname=Quick, nickname=Jess, prof=professional runner]{24}

\begin{document}

\mainFName

\sideFName

\sideLName

\mainLName

\end{document}

You need to deliver the contents of the variables. Also the group is important, otherwise unset values for a character would be carried over from a previous one. OK, unless you set all values for every character.

enter image description here

5
  • thanks a lot, this is perfect. I didn't know the \exp_not:V, very useful. Commented Apr 5, 2020 at 22:06
  • 1
    Another way would be \cs_generate_variant:Nn \cs_new_protected:Npn { cpo } then \cs_new_protected:cpo { #4 LName } { \l_character_lastname_tl }, etc. (o expands the contents of the braced argument “once”—as \expandafter would do).
    – frougon
    Commented Apr 5, 2020 at 23:13
  • @frougon I thought about that, but I abandoned the idea.
    – egreg
    Commented Apr 5, 2020 at 23:21
  • @egreg What is strange is that I got no success with the “obvious” \cs_new_protected:cpV (ERROR: You can't use `the letter m' after \the.). Ah, probably TeX doesn't know where the parameter text stops....
    – frougon
    Commented Apr 5, 2020 at 23:23
  • 1
    @frougon You can’t define a variant involving p; only N and n must be in the original function.
    – egreg
    Commented Apr 6, 2020 at 7:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .