ID:2593907
 
Code:
proc/card_link(var/c_name = "")

if(!c_name) return ""

if(!findtext(c_name,{"~"})) return c_name

usr << "DEBUG1 - [c_name]"

var/workdesc = c_name
var/newdesc = ""

while(findtext(workdesc,{"~"}))
var/chop_txt = ""
var/q_pos = findtext(workdesc,{"~"})
if(q_pos != 1)
newdesc += copytext(workdesc,1,q_pos)
workdesc = copytext(workdesc,q_pos,length(workdesc)+1)
else
workdesc = copytext(workdesc,2,length(workdesc)+1)
if(findtext(workdesc,"~"))
var/q_pos2 = findtext(workdesc,{"~"})
chop_txt = copytext(workdesc,1,q_pos2)
workdesc = copytext(workdesc,q_pos2+1,length(workdesc)+1)

usr << "DEBUG2 - =[chop_txt]="
usr << "DEBUG3 - =[lowertext(chop_txt)]="
var/obj/cards/Z
for(var/obj/cards/C in cards) if(lowertext(C.name) == lowertext(chop_txt))
usr << "DEBUG4 - [C.type] found!"
Z = new C.type
break

if(Z) chop_txt = {"<a title='[c_name]' href='?src=\ref[usr];cshow=[Z.type]'><IMG SRC=\ref[Z.icon] ICONSTATE="[Z.icon_state]" ICONDIR=NORTH></a>"}
else chop_txt = {"~[chop_txt]~"}

usr << "DEBUG5 - [chop_txt]"

newdesc += chop_txt


else

newdesc += "~[workdesc]"
workdesc = ""

if(!findtext(workdesc,{"~"}))
newdesc += workdesc


return newdesc


obj/cards/monster/PHRA

icon = 'PHRA.dmi'


EN002
name = "The Phantom Knights of Stained Greaves"
attrib = "DARK"
desc = {"If a "The Phantom Knights" monster(s) is Special Summoned to your field: You can Special Summon this card from your hand, then you can increase its Level by 1. You can banish this card from your GY; Special Summon 1 "The Phantom Knights" monster from your hand, except "The Phantom Knights of Stained Greaves", then you can increase its Level by 1. You can only use each effect of "The Phantom Knights of Stained Greaves" once per turn."}
stype = "Warrior"
icon_state = "02"
level = 3
atk = 1200
def = 600
effect = 1

EN040
name = "Raiders' Knight"
attrib = "DARK"
desc = {"2 Level 4 DARK monsters<br>(This card is always treated as a "The Phantom Knights" and "Raidraptor" card.)<br>You can detach 1 material from this card; Special Summon from your Extra Deck, 1 "The Phantom Knights", "Raidraptor", or "Xyz Dragon" monster that is 1 Rank higher or lower than this card, by using this face-up card you control as material, but destroy it during your opponent's next End Phase. (This is treated as an Xyz Summon. Transfer its materials to the Summoned monster.) You can only use this effect of "Raiders' Knight" once per turn."}
stype = "Warrior"
icon_state = "40"
rank = 4
atk = 2000
def = 0
effect = 1
xyz = 1


Problem description:

So the code above I posted is a bit of code I added to my game for converting a specific string in to a hyperlink image. If you've ever played something like World of Warcraft, its similar to the item link. If you, in chat type out "blahblah ~CARD NAME HERE~" blahblah, and it finds a card with a matching name, it'll replace that string with a picture of the card that you can click on to view its full details.

The problem is the code seems to be breaking for obj with an apostrophe in their name. In the above 2nd section of code. "The Phantom Knights of Stained Greaves" would work just fine and link the image without issue. But "Raiders' Knight" doesn't work. I'm not sure what I'm overlooking here though because the debug lines I'm using seem to indicate its not breaking.

If I run Greaves through the proc as "~The Phantom Knights of Stained Greaves~", the output results are...

DEBUG1 - ~The Phantom Knights of Stained Greaves~
DEBUG2 - =The Phantom Knights of Stained Greaves=
DEBUG3 - =the phantom knights of stained greaves=
DEBUG4 - /obj/cards/monster/PHRA/EN002 found!
DEBUG5 - INSERT HYPERLINK IMAGE HERE

But if I run Raiders' Knight through the proc as "~Raiders' Knight~", I get the following outputs...

DEBUG1 - ~Raiders' Knight~
DEBUG2 - =Raiders' Knight=
DEBUG3 - =raiders' knight=
DEBUG5 - ~Raiders' Knight~

its discovering and converting the text to lowercase like it should, but it doesn't seem to be matching it to the name of the obj.

                for(var/obj/cards/C in cards) if(lowertext(C.name) == lowertext(chop_txt))
usr << "DEBUG4 - [C.type] found!"
Z = new C.type
break


For clarification, the "cards" list in the above code is a list of the card obj in the game that players generally have access to.

This appears to be the section of the code where it's acting up but I cant figure out why. An obj with a quotation mark in the name gives the same result some I'm assuming something's breaking somewhere here due to the string not being properly enclosed but I'm not sure why. Other special characters like Hyphens work just fine.
It's probably breaking the <a> tag because it's in between apostrophes and contains one itself. You'll have to escape them or use double quotes in the tag (then escape any card names containing double quotes).

Also, cmptext() is a built-in case-insensitive text comparison.
In response to Kaiochao
Kaiochao wrote:
It's probably breaking the <a> tag because it's in between apostrophes and contains one itself. You'll have to escape them or use double quotes in the tag (then escape any card names containing double quotes).

Also, cmptext() is a built-in case-insensitive text comparison.

I would still get the DEBUG4 output line though if that's the case wouldn't I? The <a> tag is used after the fact and if that was screwing up, I'd get a garbled DEBUG5.

Instead, it's failing to match the card name to the text and not producing the DEBUG4 output and it's not assigning an obj to the Z var.
Can you confirm that the card is in the cards list?
It's there. There's only a few that aren't part of it. It's a list that's created on world creation that contains a copy of every card in the game with the exception of 2 sets, and this (PHRA) isnt one of those sets.

Other procs that use the same list have no issues finding it.

As a test, I added another card to the game. Nothing else has been changed. the new card is...

/obj/cards/monster/PHRA/EN040X

Everything about it is the same as the card above except the apostrophe is removed from the name.

It locates this card without issue but still cant find the original

https://images2.imgbox.com/dc/05/i4hgUHS8_o.png
Here's a "standalone" test project containing the code you posted, plus the minimal code to have it compile, a list of your two example cards, and a couple procs that call the proc under test:
IceFireCardLink_src.zip

I can't reproduce your issue. The link for Raiders is broken as expected, but both cards are found.

Either Raiders isn't in the cards list, or its name is changed, or something else is going on.
Yeah, I found out what the problem was. After looking over your code and realizing when it's run directly through code it works fine.

This proc is part of my chat program which has a spam filter, part of that runs html_encode() on the text. Forgot all about it. Also made it hard to notice in the chat output.

if(lowertext({"[C.name]"}) == html_decode(lowertext({"[chop_txt]"})))


fixed it